// -------------------------------------------------------------------------------- // 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 #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; }