Windows2003-3790/inetcore/outlookexpress/inetcomm/mimeole/trigger.cpp
2020-09-30 16:53:55 +02:00

1063 lines
35 KiB
C++

// --------------------------------------------------------------------------------
// Trigger.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "containx.h"
#include "symcache.h"
#include "containx.h"
#include "stackstr.h"
#include "variantx.h"
#include "mimeapi.h"
#ifndef MAC
#include <shlwapi.h>
#endif // !MAC
#include "demand.h"
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_FILENAME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_FILENAME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
BOOL fUseProperty;
LPWSTR pszExt;
LPWSTR pszFileName=NULL;
LPPROPSYMBOL pSymbol;
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_DELETEPROP:
if (pContainer->_HrIsTriggerCaller(PID_PAR_FILENAME, IST_DELETEPROP) == S_FALSE)
{
pContainer->DeleteProp(SYM_PAR_FILENAME);
}
break;
case IST_POSTSETPROP:
// Update PID_PAR_NAME, if it didn't generate this
if (pContainer->_HrIsTriggerCaller(PID_PAR_NAME, IST_POSTSETPROP) == S_FALSE)
pContainer->SetProp(SYM_PAR_NAME, dwFlags, pValue);
// Update PAR_FILENAME, if it didn't generate this
if (pContainer->_HrIsTriggerCaller(PID_PAR_FILENAME, IST_POSTSETPROP) == S_FALSE)
pContainer->SetProp(SYM_PAR_FILENAME, dwFlags, pValue);
break;
case IST_POSTGETPROP:
// Cleanup the file name
if (!ISFLAGSET(dwFlags, PDF_ENCODED))
MimeVariantCleanupFileName(pContainer->GetWindowsCP(), pValue);
break;
case IST_GETDEFAULT:
// Try to get PID_PAR_FILENAME first
if (FAILED(pContainer->GetPropW(SYM_PAR_FILENAME, &pszFileName)))
{
// Try to get PID_PAR_NAME
if (FAILED(pContainer->GetPropW(SYM_PAR_NAME, &pszFileName)))
{
hr = MIME_E_NO_DATA;
goto exit;
}
else
pSymbol = SYM_PAR_NAME;
}
else
pSymbol = SYM_PAR_FILENAME;
// Set Source
fUseProperty = TRUE;
// Locate the extension of the file
pszExt = PathFindExtensionW(pszFileName);
// If .com
if (pszExt && StrCmpIW(pszExt, L".com") == 0)
{
// Locals
LPWSTR pszCntType=NULL;
LPWSTR pszSubType=NULL;
// Get the file information
if (SUCCEEDED(MimeOleGetFileInfoW(pszFileName, &pszCntType, &pszSubType, NULL, NULL, NULL)))
{
// Extension is .com and content types don't match what is in the body
if (pContainer->IsContentTypeW(pszCntType, pszSubType) == S_FALSE)
{
// Generate It
if (SUCCEEDED(pContainer->_HrGenerateFileName(NULL, dwFlags, pValue)))
fUseProperty = FALSE;
}
}
// Cleanup
SafeMemFree(pszCntType);
SafeMemFree(pszSubType);
}
// Raid-63402: OE: cc: mail problems with OE
// Empty file extension ?
else if (NULL == pszExt || L'\0' == *pszExt)
{
// Generate a new filename
CHECKHR(hr = pContainer->_HrGenerateFileName(pszFileName, dwFlags, pValue));
// Done
fUseProperty = FALSE;
}
// Return per user request
if (fUseProperty)
{
// Use the property
CHECKHR(hr = pContainer->GetProp(pSymbol, dwFlags, pValue));
}
// Cleanup the file name
if (!ISFLAGSET(dwFlags, PDF_ENCODED))
MimeVariantCleanupFileName(pContainer->GetWindowsCP(), pValue);
break;
}
exit:
// Cleanup
SafeMemFree(pszFileName);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_GENFNAME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_GENFNAME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPPROPERTY pProperty;
LPSTR pszDefExt=NULL,
pszData=NULL,
pszFree=NULL,
pszSuggest=NULL;
LPCSTR pszCntType=NULL;
MIMEVARIANT rSource;
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_POSTGETPROP:
if (!ISFLAGSET(dwFlags, PDF_ENCODED))
MimeVariantCleanupFileName(pContainer->GetWindowsCP(), pValue);
break;
case IST_GETDEFAULT:
// Try to just get the normal filename
if (SUCCEEDED(TRIGGER_ATT_FILENAME(pContainer, IST_GETDEFAULT, dwFlags, pValue, NULL)))
goto exit;
// Call back into the container
CHECKHR(hr = pContainer->_HrGenerateFileName(NULL, dwFlags, pValue));
// Cleanup the file name
if (!ISFLAGSET(dwFlags, PDF_ENCODED))
MimeVariantCleanupFileName(pContainer->GetWindowsCP(), pValue);
break;
}
exit:
// Cleanup
SafeMemFree(pszData);
SafeMemFree(pszFree);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_NORMSUBJ
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_NORMSUBJ(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
MIMEVARIANT rSubject;
MIMEVARIANT rNormal;
LPSTR pszNormal,
pszFree=NULL;
LPWSTR pszNormalW,
pszFreeW=NULL;
ULONG i=0,
cch=0;
LPPROPERTY pSubject;
// Handle Dispatch Type
if (IST_GETDEFAULT == tyTrigger)
{
// Get Subject
pSubject = pContainer->m_prgIndex[PID_HDR_SUBJECT];
// No Data
if (NULL == pSubject)
{
hr = MIME_E_NO_DATA;
goto exit;
}
switch (pValue->type)
{
case MVT_STRINGA:
{
// Set Subject Type
rSubject.type = MVT_STRINGA;
// Return per user request
CHECKHR(hr = pContainer->HrConvertVariant(pSubject, CVF_NOALLOC, &rSubject));
// Set Normal subject
pszFree = rSubject.fCopy ? NULL : rSubject.rStringA.pszVal;
pszNormal = rSubject.rStringA.pszVal;
// Less than 5 "xxx: "
if (rSubject.rStringA.cchVal >= 4)
{
// 1, 2, 3, 4 spaces followed by a ':' then a space
while (cch < 7 && i < rSubject.rStringA.cchVal)
{
// Skip Lead Bytes
if (IsDBCSLeadByte(rSubject.rStringA.pszVal[i]))
{
i++;
cch++;
}
// Colon
else if (':' == rSubject.rStringA.pszVal[i])
{
if (i+1 >= rSubject.rStringA.cchVal)
{
i++;
pszNormal = (LPSTR)(rSubject.rStringA.pszVal + i);
break;
}
else if (cch <= 4 && ' ' == rSubject.rStringA.pszVal[i+1])
{
i++;
pszNormal = PszSkipWhiteA((LPSTR)(rSubject.rStringA.pszVal + i));
break;
}
else
break;
}
// Next Character
i++;
cch++;
}
}
// Reset Source
if (pszNormal != rSubject.rStringA.pszVal)
{
rSubject.rStringA.pszVal = pszNormal;
rSubject.rStringA.cchVal = lstrlen(pszNormal);
}
break;
}
case MVT_STRINGW:
{
// Set Subject Type
rSubject.type = MVT_STRINGW;
// Return per user request
CHECKHR(hr = pContainer->HrConvertVariant(pSubject, CVF_NOALLOC, &rSubject));
// Set Normal subject
pszFreeW = rSubject.fCopy ? NULL : rSubject.rStringW.pszVal;
pszNormalW = rSubject.rStringW.pszVal;
// Less than 5 "xxx: "
if (rSubject.rStringW.cchVal >= 4)
{
// 1, 2, or 3 spaces followed by a ':' then a space
while (cch < 7 && i < rSubject.rStringW.cchVal)
{
// Colon
if (L':' == rSubject.rStringW.pszVal[i])
{
if (i+1 >= rSubject.rStringW.cchVal)
{
i++;
pszNormalW = (LPWSTR)(rSubject.rStringW.pszVal + i);
break;
}
else if (cch <= 4 && L' ' == rSubject.rStringW.pszVal[i+1])
{
i++;
pszNormalW = PszSkipWhiteW((LPWSTR)(rSubject.rStringW.pszVal + i));
break;
}
else
break;
}
// Next Character
i++;
cch++;
}
}
// Reset Source
if (pszNormalW != rSubject.rStringW.pszVal)
{
rSubject.rStringW.pszVal = pszNormalW;
rSubject.rStringW.cchVal = lstrlenW(pszNormalW);
}
break;
}
default:
AssertSz(FALSE, "Didn't prepare for this type!!!");
break;
}
// Return per user request
CHECKHR(hr = pContainer->HrConvertVariant(pSubject->pSymbol, pSubject->pCharset, IET_DECODED, dwFlags, 0, &rSubject, pValue));
}
exit:
// Cleanup
SafeMemFree(pszFree);
SafeMemFree(pszFreeW);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_HDR_SUBJECT
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_HDR_SUBJECT(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Handle Dispatch type
if (IST_DELETEPROP == tyTrigger)
pContainer->DeleteProp(SYM_ATT_NORMSUBJ);
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_HDR_CNTTYPE
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_HDR_CNTTYPE(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
CStringParser cString;
CHAR chToken;
MIMEVARIANT rValue;
LPSTR pszCntType=NULL;
// Invalid Arg
Assert(pContainer);
// Handle Dispatch type
switch(tyTrigger)
{
case IST_DELETEPROP:
pContainer->DeleteProp(SYM_ATT_PRITYPE);
pContainer->DeleteProp(SYM_ATT_SUBTYPE);
break;
case IST_POSTSETPROP:
// If not generated from corresponding atributes
if (pContainer->_HrIsTriggerCaller(PID_ATT_PRITYPE, IST_POSTSETPROP) == S_OK ||
pContainer->_HrIsTriggerCaller(PID_ATT_SUBTYPE, IST_POSTSETPROP) == S_OK)
goto exit;
// Validate the Variant
if (ISSTRINGA(pValue))
{
// Locals
CHAR szPriType[255];
// Set the Members
cString.Init(pValue->rStringA.pszVal, pValue->rStringA.cchVal, PSF_NOTRAILWS | PSF_NOCOMMENTS);
// Set Parse Tokens
chToken = cString.ChParse("/");
if ('\0' == chToken && 0 == cString.CchValue())
goto exit;
// Setup the Variant
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = (LPSTR)cString.PszValue();
rValue.rStringA.cchVal = cString.CchValue();
// Save Primary Type
StrCpyN(szPriType, rValue.rStringA.pszVal, ARRAYSIZE(szPriType));
// Add New attribute...
CHECKHR(hr = pContainer->SetProp(SYM_ATT_PRITYPE, 0, &rValue));
// Raid-52462: outlook express: mail with bad content type header comes in as an attachment
// Seek end of sub content-type
chToken = cString.ChParse(" ;");
if (0 == cString.CchValue())
{
// Locals
LPCSTR pszSubType = PszDefaultSubType(szPriType);
ULONG cchCntType;
// Set Default SubType
CHECKHR(hr = pContainer->SetProp(SYM_ATT_SUBTYPE, pszSubType));
// Build ContentType
DWORD cchSize = (lstrlen(szPriType) + lstrlen(pszSubType) + 2);
CHECKALLOC(pszCntType = PszAllocA(cchSize));
// Format the ContentType
cchCntType = wnsprintf(pszCntType, cchSize, "%s/%s", szPriType, pszSubType);
// Setup a variant
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = (LPSTR)pszCntType;
rValue.rStringA.cchVal = cchCntType;
// Store the variant data
Assert(pContainer->m_prgIndex[PID_HDR_CNTTYPE]);
CHECKHR(hr = pContainer->_HrStoreVariantValue(pContainer->m_prgIndex[PID_HDR_CNTTYPE], 0, &rValue));
// Done
goto exit;
}
// Setup the Variant
rValue.rStringA.pszVal = (LPSTR)cString.PszValue();
rValue.rStringA.cchVal = cString.CchValue();
// Add New attribute...
CHECKHR(hr = pContainer->SetProp(SYM_ATT_SUBTYPE, 0, &rValue));
// We should be done
Assert(';' == chToken || '(' == chToken || '\0' == chToken || ' ' == chToken);
}
break;
case IST_GETDEFAULT:
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = (LPSTR)STR_MIME_TEXT_PLAIN;
rValue.rStringA.cchVal = lstrlen(STR_MIME_TEXT_PLAIN);
CHECKHR(hr = pContainer->HrConvertVariant(SYM_HDR_CNTTYPE, NULL, IET_DECODED, dwFlags, 0, &rValue, pValue));
break;
}
exit:
// Cleanup
SafeMemFree(pszCntType);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_PRITYPE
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_PRITYPE(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPPROPERTY pSubType;
LPSTR pszSubType;
ULONG cchSubType;
MIMEVARIANT rValue;
// Define a Stack String
STACKSTRING_DEFINE(rContentType, 255);
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_POSTSETPROP:
{
// If inside content type dispatch setprop
if (pContainer->_HrIsTriggerCaller(PID_HDR_CNTTYPE, IST_POSTSETPROP) == S_OK)
goto exit;
// Asser Type
Assert(pValue && ISSTRINGA(pValue));
// Get pCntType
pSubType = pContainer->m_prgIndex[PID_ATT_SUBTYPE];
// Is the subtype set yet
if (pSubType)
{
Assert(ISSTRINGA(&pSubType->rValue));
pszSubType = pSubType->rValue.rStringA.pszVal;
cchSubType = pSubType->rValue.rStringA.cchVal;
}
else
{
pszSubType = (LPSTR)STR_SUB_PLAIN;
cchSubType = lstrlen(STR_SUB_PLAIN);
}
// Make Sure the stack string can hold the data
DWORD cchSize = (cchSubType + pValue->rStringA.cchVal + 2);
STACKSTRING_SETSIZE(rContentType, cchSize);
// Init rValue
ZeroMemory(&rValue, sizeof(MIMEVARIANT));
// Format the content type
rValue.rStringA.cchVal = wnsprintf(rContentType.pszVal, cchSize, "%s/%s", pValue->rStringA.pszVal, pszSubType);
// Setup the value
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = rContentType.pszVal;
// SetProp
CHECKHR(hr = pContainer->SetProp(SYM_HDR_CNTTYPE, 0, &rValue));
}
break;
case IST_GETDEFAULT:
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = (LPSTR)STR_CNT_TEXT;
rValue.rStringA.cchVal = lstrlen(STR_CNT_TEXT);
CHECKHR(hr = pContainer->HrConvertVariant(SYM_HDR_CNTTYPE, NULL, IET_DECODED, dwFlags, 0, &rValue, pValue));
break;
}
exit:
// Cleanup
STACKSTRING_FREE(rContentType);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_SUBTYPE
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_SUBTYPE(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPPROPERTY pPriType;
LPSTR pszPriType;
ULONG cchPriType;
MIMEVARIANT rValue;
// Define a Stack String
STACKSTRING_DEFINE(rContentType, 255);
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_POSTSETPROP:
{
// If inside content type dispatch setprop
if (pContainer->_HrIsTriggerCaller(PID_HDR_CNTTYPE, IST_POSTSETPROP) == S_OK)
goto exit;
// Asser Type
Assert(pValue && ISSTRINGA(pValue));
// Get pCntType
pPriType = pContainer->m_prgIndex[PID_ATT_PRITYPE];
// Is the subtype set yet
if (pPriType)
{
Assert(ISSTRINGA(&pPriType->rValue));
pszPriType = pPriType->rValue.rStringA.pszVal;
cchPriType = pPriType->rValue.rStringA.cchVal;
}
else
{
pszPriType = (LPSTR)STR_CNT_TEXT;
cchPriType = lstrlen(STR_CNT_TEXT);
}
// Make Sure the stack string can hold the data
DWORD cchSize = (cchPriType + pValue->rStringA.cchVal + 2);
STACKSTRING_SETSIZE(rContentType, cchSize);
// Init rValue
ZeroMemory(&rValue, sizeof(MIMEVARIANT));
// Format the content type
rValue.rStringA.cchVal = wnsprintf(rContentType.pszVal, cchSize, "%s/%s", pszPriType, pValue->rStringA.pszVal);
// Setup the value
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = rContentType.pszVal;
// SetProp
CHECKHR(hr = pContainer->SetProp(SYM_HDR_CNTTYPE, 0, &rValue));
}
break;
case IST_GETDEFAULT:
rValue.type = MVT_STRINGA;
rValue.rStringA.pszVal = (LPSTR)STR_SUB_PLAIN;
rValue.rStringA.cchVal = lstrlen(STR_SUB_PLAIN);
CHECKHR(hr = pContainer->HrConvertVariant(SYM_HDR_CNTTYPE, NULL, IET_DECODED, dwFlags, 0, &rValue, pValue));
break;
}
exit:
// Cleanup
STACKSTRING_FREE(rContentType);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_HDR_CNTXFER
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_HDR_CNTXFER(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
MIMEVARIANT rSource;
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_GETDEFAULT:
rSource.type = MVT_STRINGA;
rSource.rStringA.pszVal = (LPSTR)STR_ENC_7BIT;
rSource.rStringA.cchVal = lstrlen(STR_ENC_7BIT);
CHECKHR(hr = pContainer->HrConvertVariant(SYM_HDR_CNTXFER, NULL, IET_DECODED, dwFlags, 0, &rSource, pValue));
break;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_PAR_NAME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_PAR_NAME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Handle Dispatch type
switch(tyTrigger)
{
case IST_POSTSETPROP:
if (pContainer->_HrIsTriggerCaller(PID_ATT_FILENAME, IST_POSTSETPROP) == S_FALSE)
pContainer->SetProp(SYM_ATT_FILENAME, dwFlags, pValue);
break;
}
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_PAR_FILENAME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_PAR_FILENAME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Handle Dispatch type
switch(tyTrigger)
{
case IST_DELETEPROP:
if (pContainer->_HrIsTriggerCaller(PID_ATT_FILENAME, IST_DELETEPROP) == S_FALSE)
pContainer->DeleteProp(SYM_ATT_FILENAME);
break;
case IST_POSTSETPROP:
if (pContainer->_HrIsTriggerCaller(PID_ATT_FILENAME, IST_POSTSETPROP) == S_FALSE)
pContainer->SetProp(SYM_ATT_FILENAME, dwFlags, pValue);
break;
}
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_SENTTIME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_SENTTIME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
// Handle Dispatch type
switch(tyTrigger)
{
case IST_DELETEPROP:
pContainer->DeleteProp(SYM_HDR_DATE);
break;
case IST_POSTSETPROP:
pContainer->SetProp(SYM_HDR_DATE, dwFlags, pValue);
break;
case IST_GETDEFAULT:
// Raid-39471-Mail: Date showing as jan 01, 1601 in readnote for attached message
if (FAILED(pContainer->GetProp(SYM_HDR_DATE, dwFlags, pValue)))
{
// Get Known Property
LPPROPERTY pProperty = pContainer->m_prgIndex[PID_HDR_RECEIVED];
if (pProperty && ISSTRINGA(&pProperty->rValue))
{
// Try Getting Sent Time
CHECKHR(hr = pContainer->GetProp(SYM_ATT_RECVTIME, dwFlags, pValue));
}
else
{
// Locals
SYSTEMTIME st;
MIMEVARIANT rValue;
// Setup rValue
rValue.type = MVT_VARIANT;
rValue.rVariant.vt = VT_FILETIME;
// Get current systemtime
GetSystemTime(&st);
SystemTimeToFileTime(&st, &rValue.rVariant.filetime);
// If the Conversion Fails, get the current time
CHECKHR(hr = pContainer->HrConvertVariant(SYM_ATT_SENTTIME, NULL, IET_DECODED, dwFlags, 0, &rValue, pValue));
}
}
break;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_RECVTIME
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_RECVTIME(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
MIMEVARIANT rSource;
LPMIMEVARIANT pSource;
LPPROPERTY pProperty;
// Handle Dispatch Type
switch(tyTrigger)
{
case IST_DELETEPROP:
pContainer->DeleteProp(SYM_HDR_RECEIVED);
break;
case IST_GETDEFAULT:
// Get Known Property
pProperty = pContainer->m_prgIndex[PID_HDR_RECEIVED];
if (NULL == pProperty || !ISSTRINGA(&pProperty->rValue))
{
// Try Getting Sent Time
MimeOleGetSentTime(pContainer, dwFlags, pValue);
}
// Otherwise, try to convert it
else
{
// If StringA
if (MVT_STRINGA == pProperty->rValue.type)
{
// Find the first header which has a semi-colon in it
while(1)
{
// Seek to last colon
LPSTR psz = pProperty->rValue.rStringA.pszVal;
int i;
for (i = 0; psz[i] ; i++);
rSource.rStringA.pszVal = psz + i; // set to end of string
for (; i >= 0 ; i--)
{
if (psz[i] == ';')
{
rSource.rStringA.pszVal = psz + i;
break;
}
}
if ('\0' == *rSource.rStringA.pszVal)
{
// No more values
if (NULL == pProperty->pNextValue)
{
// Try Getting Sent Time
MimeOleGetSentTime(pContainer, dwFlags, pValue);
// Done
goto exit;
}
// Goto next
pProperty = pProperty->pNextValue;
}
// Otherwise, we must have a good property
else
break;
}
// Step over ';
rSource.rStringA.pszVal++;
// Setup Source
rSource.type = MVT_STRINGA;
rSource.rStringA.cchVal = lstrlen(rSource.rStringA.pszVal);
pSource = &rSource;
}
// Otherwise, just try to conver the current property data
else
pSource = &pProperty->rValue;
// If the Conversion Fails, get the current time
if (FAILED(pContainer->HrConvertVariant(SYM_ATT_RECVTIME, NULL, IET_DECODED, dwFlags, 0, pSource, pValue)))
{
// Try Getting Sent Time
MimeOleGetSentTime(pContainer, dwFlags, pValue);
}
}
break;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CMimePropertyContainer::TRIGGER_ATT_PRIORITY
// --------------------------------------------------------------------------------
HRESULT CMimePropertyContainer::TRIGGER_ATT_PRIORITY(LPCONTAINER pContainer, TRIGGERTYPE tyTrigger,
DWORD dwFlags, LPMIMEVARIANT pValue, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
MIMEVARIANT rSource;
PROPVARIANT rVariant;
LPMIMEVARIANT pSource;
LPPROPERTY pProperty;
// Handle Dispatch type
switch(tyTrigger)
{
// IST_VARIANT_TO_STRINGA
case IST_VARIANT_TO_STRINGA:
Assert(pValue && pDest && MVT_VARIANT == pValue->type && MVT_STRINGA == pDest->type);
if (VT_UI4 != pValue->rVariant.vt)
{
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
switch(pValue->rVariant.ulVal)
{
// IMSG_PRI_LOW
case IMSG_PRI_LOW:
pDest->rStringA.pszVal = (LPSTR)STR_PRI_MS_LOW;
pDest->rStringA.cchVal = lstrlen(STR_PRI_MS_LOW);
break;
// IMSG_PRI_HIGH
case IMSG_PRI_HIGH:
pDest->rStringA.pszVal = (LPSTR)STR_PRI_MS_HIGH;
pDest->rStringA.cchVal = lstrlen(STR_PRI_MS_HIGH);
break;
// IMSG_PRI_NORMAL
default:
case IMSG_PRI_NORMAL:
pDest->rStringA.pszVal = (LPSTR)STR_PRI_MS_NORMAL;
pDest->rStringA.cchVal = lstrlen(STR_PRI_MS_NORMAL);
break;
}
break;
// IST_VARIANT_TO_STRINGW
case IST_VARIANT_TO_STRINGW:
Assert(pValue && pDest && MVT_VARIANT == pValue->type && MVT_STRINGW == pDest->type);
if (VT_UI4 != pValue->rVariant.vt)
{
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
switch(pValue->rVariant.ulVal)
{
// IMSG_PRI_LOW
case IMSG_PRI_LOW:
#ifndef WIN16
pDest->rStringW.pszVal = L"Low";
#else
pDest->rStringW.pszVal = "Low";
#endif // !WIN16
pDest->rStringW.cchVal = 3;
break;
// IMSG_PRI_HIGH
case IMSG_PRI_HIGH:
#ifndef WIN16
pDest->rStringW.pszVal = L"High";
#else
pDest->rStringW.pszVal = "High";
#endif // !WIN16
pDest->rStringW.cchVal = 4;
break;
// IMSG_PRI_NORMAL
default:
case IMSG_PRI_NORMAL:
#ifndef WIN16
pDest->rStringW.pszVal = L"Normal";
#else
pDest->rStringW.pszVal = "Normal";
#endif // !WIN16
pDest->rStringW.cchVal = 6;
break;
}
break;
// IST_VARIANT_TO_VARIANT
case IST_VARIANT_TO_VARIANT:
Assert(pValue && pDest && MVT_VARIANT == pValue->type && MVT_VARIANT == pDest->type);
if (VT_UI4 != pValue->rVariant.vt && VT_UI4 != pDest->rVariant.vt)
{
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
// Nice and Easy
pDest->rVariant.ulVal = pValue->rVariant.ulVal;
break;
// IST_STRINGA_TO_VARIANT
case IST_STRINGA_TO_VARIANT:
Assert(pValue && pDest && MVT_STRINGA == pValue->type && MVT_VARIANT == pDest->type);
if (VT_UI4 != pDest->rVariant.vt)
{
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
// Priority From String
pDest->rVariant.ulVal = PriorityFromStringA(pValue->rStringA.pszVal);
break;
// IST_STRINGW_TO_VARIANT
case IST_STRINGW_TO_VARIANT:
Assert(pValue && pDest && MVT_STRINGW == pValue->type && MVT_VARIANT == pDest->type);
if (VT_UI4 != pDest->rVariant.vt)
{
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
// Priority From String
pDest->rVariant.ulVal = PriorityFromStringW(pValue->rStringW.pszVal);
break;
// IST_DELETEPROP
case IST_DELETEPROP:
pContainer->DeleteProp(SYM_HDR_XPRI);
pContainer->DeleteProp(SYM_HDR_XMSPRI);
break;
// IST_POSTSETPROP
case IST_POSTSETPROP:
// Setup rSource
rSource.type = MVT_VARIANT;
rSource.rVariant.vt = VT_UI4;
// Convert to User's Variant to a Integer Priority
CHECKHR(hr = pContainer->HrConvertVariant(SYM_ATT_PRIORITY, NULL, IET_DECODED, 0, 0, pValue, &rSource));
// Setup rVariant
rVariant.vt = VT_LPSTR;
// Switch on priority
switch(rSource.rVariant.ulVal)
{
case IMSG_PRI_LOW:
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XMSPRI), STR_PRI_MS_LOW));
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XPRI), STR_PRI_LOW));
break;
case IMSG_PRI_NORMAL:
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XMSPRI), STR_PRI_MS_NORMAL));
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XPRI), STR_PRI_NORMAL));
break;
case IMSG_PRI_HIGH:
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XMSPRI), STR_PRI_MS_HIGH));
CHECKHR(hr = pContainer->SetProp(PIDTOSTR(PID_HDR_XPRI), STR_PRI_HIGH));
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
// Done
break;
// IST_GETDEFAULT
case IST_GETDEFAULT:
// Get the Priority Property
pProperty = pContainer->m_prgIndex[PID_HDR_XPRI];
if (NULL == pProperty)
pProperty = pContainer->m_prgIndex[PID_HDR_XMSPRI];
// No Data
if (NULL == pProperty)
{
rSource.type = MVT_VARIANT;
rSource.rVariant.vt = VT_UI4;
rSource.rVariant.ulVal = IMSG_PRI_NORMAL;
pSource = &rSource;
}
// Otherwise
else
pSource = &pProperty->rValue;
// Convert to User's Variant
CHECKHR(hr = pContainer->HrConvertVariant(SYM_ATT_PRIORITY, NULL, IET_DECODED, dwFlags, 0, pSource, pValue));
// Done
break;
}
exit:
// Done
return hr;
}