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

1656 lines
49 KiB
C++

// --------------------------------------------------------------------------------
// VariantX.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "variantx.h"
#include "wchar.h"
#include "internat.h"
#include "symcache.h"
#include "dllmain.h"
#include "containx.h"
#include <shlwapi.h>
#include "mimeapi.h"
#include "strconst.h"
#include "demand.h"
// --------------------------------------------------------------------------------
// Helper Prototypes
// --------------------------------------------------------------------------------
HRESULT HrWriteHeaderFormatA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT HrWriteHeaderFormatW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT HrWriteNameInDataA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT HrWriteNameInDataW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
// --------------------------------------------------------------------------------
// International Conversion Prototypes
// --------------------------------------------------------------------------------
HRESULT Internat_StringA_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPSTR *);
HRESULT Internat_StringA_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPWSTR *);
HRESULT Internat_StringW_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPWSTR *);
HRESULT Internat_StringW_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT, LPSTR *);
// --------------------------------------------------------------------------------
// Variant Conversion Function Prototype
// --------------------------------------------------------------------------------
typedef HRESULT (APIENTRY *PFNVARIANTCONVERT)(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
// --------------------------------------------------------------------------------
// Converter Prototypes
// --------------------------------------------------------------------------------
HRESULT StringA_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT StringA_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT StringA_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT StringW_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT StringW_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT StringW_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT Variant_To_StringA(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT Variant_To_StringW(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
HRESULT Variant_To_Variant(LPVARIANTCONVERT, LPMIMEVARIANT, LPMIMEVARIANT);
// --------------------------------------------------------------------------------
// VCASSERTARGS - Common Invalid Arg Assert Macro
// --------------------------------------------------------------------------------
#define VCASSERTARGS(_typeSource, _typeDest) \
Assert(pConvert && pSource && pDest && pSource->type == _typeSource); \
if (MVT_STRINGA == _typeDest) \
Assert(MVT_STRINGA == pDest->type || MVT_STREAM == pDest->type); \
else if (MVT_STRINGW == _typeDest) \
Assert(MVT_STRINGW == pDest->type || MVT_STREAM == pDest->type); \
else \
Assert(_typeDest == pDest->type);
// --------------------------------------------------------------------------------
// VARIANTCONVERTMAP
// --------------------------------------------------------------------------------
typedef struct tagVARIANTCONVERTMAP {
PFNVARIANTCONVERT pfnConvertTo[MVT_LAST];
} VARIANTCONVERTMAP;
// --------------------------------------------------------------------------------
// PVC - Cast to PFNVARIANTCONVERT
// --------------------------------------------------------------------------------
#define PVC(_function) ((PFNVARIANTCONVERT)_function)
// --------------------------------------------------------------------------------
// Variant Conversion Map
// --------------------------------------------------------------------------------
static const VARIANTCONVERTMAP g_rgVariantX[MVT_LAST - 1] = {
{ NULL, NULL, NULL, NULL, NULL }, // MVT_EMPTY
{ NULL, PVC(StringA_To_StringA), PVC(StringA_To_StringW), PVC(StringA_To_Variant), PVC(StringA_To_StringA) }, // MVT_STRINGA / MVT_STREAM
{ NULL, PVC(StringW_To_StringA), PVC(StringW_To_StringW), PVC(StringW_To_Variant), PVC(StringW_To_StringA) }, // MVT_STRINGW
{ NULL, PVC(Variant_To_StringA), PVC(Variant_To_StringW), PVC(Variant_To_Variant), PVC(Variant_To_StringA) }, // MVT_VARIANT
};
// --------------------------------------------------------------------------------
// _HrConvertVariant - Looks up the correct Variant Conversion function
// --------------------------------------------------------------------------------
#define _HrConvertVariant(_typeSource, _typeDest, _pConvert, _pSource, _pDest) \
(*(g_rgVariantX[_typeSource].pfnConvertTo[_typeDest]))(_pConvert, _pSource, _pDest)
// --------------------------------------------------------------------------------
// HrConvertVariant
// --------------------------------------------------------------------------------
HRESULT HrConvertVariant(
/* in */ LPHEADOPTIONS pOptions,
/* in */ LPPROPSYMBOL pSymbol,
/* in */ LPINETCSETINFO pCharset,
/* in */ ENCODINGTYPE ietSource,
/* in */ DWORD dwFlags,
/* in */ DWORD dwState,
/* in */ LPMIMEVARIANT pSource,
/* in,out */ LPMIMEVARIANT pDest,
/* out,opt */ BOOL *pfRfc1522 /* = NULL */)
{
// Locals
HRESULT hr=S_OK;
VARIANTCONVERT rConvert;
// Invalid Arg
Assert(pOptions && pSymbol && pSource && pDest && pOptions->pDefaultCharset);
Assert(IET_ENCODED == ietSource || IET_DECODED == ietSource);
// Init
if (pfRfc1522)
*pfRfc1522 = FALSE;
// Failure
if (!ISVALIDVARTYPE(pSource->type) || !ISVALIDVARTYPE(pDest->type))
{
AssertSz(FALSE, "An invalid VARTYPE was encountered!");
hr = TraceResult(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
// Init pDest
pDest->fCopy = FALSE;
// Init rConvert
ZeroMemory(&rConvert, sizeof(VARIANTCONVERT));
rConvert.pOptions = pOptions;
rConvert.pSymbol = pSymbol;
rConvert.pCharset = pCharset ? pCharset : pOptions->pDefaultCharset;
rConvert.ietSource = ietSource;
rConvert.dwFlags = dwFlags;
rConvert.dwState = dwState;
// Remove PRSTATE_RFC1522
FLAGCLEAR(rConvert.dwState, PRSTATE_RFC1522);
// Valid Charset
Assert(g_rgVariantX[pSource->type].pfnConvertTo[pDest->type]);
// Remove Comments and fixup the source...
if (ISFLAGSET(dwFlags, PDF_NOCOMMENTS) && (MVT_STRINGA == pSource->type || MVT_STRINGW == pSource->type))
{
// Locals
MIMEVARIANT rVariant;
BYTE rgbScratch[256];
// Init
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
// Strip Comments
if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
{
// Change the Source
pSource = &rVariant;
// Remove CF_NOALLOC
FLAGCLEAR(dwFlags, CVF_NOALLOC);
}
// Do the Conversion
hr = _HrConvertVariant(pSource->type, pDest->type, &rConvert, pSource, pDest);
// Free the Variant
MimeVariantFree(&rVariant);
// Failure
if (FAILED(hr))
{
TrapError(hr);
goto exit;
}
}
// Otherwise, normal Conversion
else
{
// Do the Conversion
CHECKHR(hr = _HrConvertVariant(pSource->type, pDest->type, &rConvert, pSource, pDest));
}
// 1522 Encoded ?
if (pfRfc1522 && ISFLAGSET(rConvert.dwState, PRSTATE_RFC1522))
*pfRfc1522 = TRUE;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringA_To_StringA
// --------------------------------------------------------------------------------
HRESULT StringA_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPSTR pszFree=NULL;
MIMEVARIANT rVariant;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
// Invalid Arg
if (ISVALIDSTRINGA(&pSource->rStringA) == FALSE)
return TrapError(E_INVALIDARG);
// Init pDest
if (MVT_STRINGA == pDest->type)
{
pDest->rStringA.pszVal = NULL;
pDest->rStringA.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
rVariant.type = MVT_STRINGA;
// Is International Property
CHECKHR(hr = Internat_StringA_To_StringA(pConvert, pSource, &rVariant, &pszFree));
// If Transmit, setup wrapinfo
if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
{
// WriteHeaderFormatA
CHECKHR(hr = HrWriteHeaderFormatA(pConvert, &rVariant, pDest));
}
// Wanted in a stream
else if (MVT_STREAM == pDest->type)
{
// No Stream...
if (NULL == pDest->pStream)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Write to the stream
CHECKHR(hr = pDest->pStream->Write(rVariant.rStringA.pszVal, rVariant.rStringA.cchVal, NULL));
}
// MVT_STRINGA
else if (MVT_STRINGA == pDest->type)
{
// If Writing Transmit (Write Header Name)
if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
{
// Write Name Into Data
CHECKHR(hr = HrWriteNameInDataA(pConvert, &rVariant, pDest));
}
// No Conversion
else if (rVariant.rStringA.pszVal == pSource->rStringA.pszVal)
{
// Copy
CHECKHR(hr = HrMimeVariantCopy(pConvert->dwFlags, &rVariant, pDest));
}
// Is Equal to pszFree
else if (rVariant.rStringA.pszVal == pszFree)
{
// Just Copy It
CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
// Not a copy
pDest->fCopy = FALSE;
// Don't free pszFree
pszFree = NULL;
}
// Big Problem
else
Assert(FALSE);
}
// Big Problem
else
Assert(FALSE);
exit:
// Cleanup
SafeMemFree(pszFree);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringA_To_StringW
// --------------------------------------------------------------------------------
HRESULT StringA_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pszFree=NULL;
MIMEVARIANT rVariant;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGW);
// Invalid Arg
if (ISVALIDSTRINGA(&pSource->rStringA) == FALSE)
return TrapError(E_INVALIDARG);
// Init pDest
if (MVT_STRINGW == pDest->type)
{
pDest->rStringW.pszVal = NULL;
pDest->rStringW.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
rVariant.type = MVT_STRINGW;
// Internat Conversion
CHECKHR(hr = Internat_StringA_To_StringW(pConvert, pSource, &rVariant, &pszFree));
// If Transmit, setup wrapinfo
if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
{
// WriteHeaderFormatW
CHECKHR(hr = HrWriteHeaderFormatW(pConvert, &rVariant, pDest));
}
// MVT_STREAM
else if (MVT_STREAM == pDest->type)
{
// No Stream...
if (NULL == pDest->pStream)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Write to the stream
CHECKHR(hr = pDest->pStream->Write(rVariant.rStringW.pszVal, rVariant.rStringW.cchVal, NULL));
}
// MVT_STRINGW
else if (MVT_STRINGW == pDest->type)
{
// If Writing Transmit (Write Header Name)
if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
{
CHECKHR(hr = HrWriteNameInDataW(pConvert, &rVariant, pDest));
}
// Equal to Data that we Allocated
else if (rVariant.rStringW.pszVal == pszFree)
{
// Copy Memory
CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
// Not a copy
pDest->fCopy = FALSE;
// Don't Free pszFree
pszFree = NULL;
}
// Big Problem
else
Assert(FALSE);
}
// Big Problem
else
Assert(FALSE);
exit:
// Cleanup
SafeMemFree(pszFree);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringA_To_Variant
// --------------------------------------------------------------------------------
HRESULT StringA_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPSTR psz;
MIMEVARIANT rVariant;
BYTE rgbScratch[255];
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_VARIANT);
Assert(!ISFLAGSET(pConvert->dwFlags, PDF_ENCODED) && !ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT));
// Init
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
// See If Symbol has a custom Translator...
if (ISTRIGGERED(pConvert->pSymbol, IST_STRINGA_TO_VARIANT))
{
// Call the Translator
CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_STRINGA_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
}
// Otherwise, use default converter
else
{
// Handle Variant Type
switch(pDest->rVariant.vt)
{
case VT_UI4:
// Strip Comments
if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
pSource = &rVariant;
// Convert to ULONG
pDest->rVariant.ulVal = strtoul(pSource->rStringA.pszVal, &psz, 10);
break;
case VT_I4:
// Strip Comments
if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
pSource = &rVariant;
// Convert to Long
pDest->rVariant.lVal = strtol(pSource->rStringA.pszVal, &psz, 10);
break;
case VT_FILETIME:
CHECKHR(hr = MimeOleInetDateToFileTime(pSource->rStringA.pszVal, &pDest->rVariant.filetime));
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
}
exit:
// Cleanup
MimeVariantFree(&rVariant);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringW_To_StringA
// --------------------------------------------------------------------------------
HRESULT StringW_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPSTR pszFree=NULL;
MIMEVARIANT rVariant;
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_STRINGA);
// Invalid Arg
if (ISVALIDSTRINGW(&pSource->rStringW) == FALSE)
return TrapError(E_INVALIDARG);
// Init pDest
if (MVT_STRINGA == pDest->type)
{
pDest->rStringA.pszVal = NULL;
pDest->rStringA.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
rVariant.type = MVT_STRINGA;
// Internat Conversion
CHECKHR(hr = Internat_StringW_To_StringA(pConvert, pSource, &rVariant, &pszFree));
// If Transmit, setup wrapinfo
if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
{
// WriteHeaderFormatA
CHECKHR(hr = HrWriteHeaderFormatA(pConvert, &rVariant, pDest));
}
// Wanted in a stream
else if (MVT_STREAM == pDest->type)
{
// No Stream...
if (NULL == pDest->pStream)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Write to the stream
CHECKHR(hr = pDest->pStream->Write(rVariant.rStringA.pszVal, rVariant.rStringA.cchVal, NULL));
}
// MVT_STRINGA
else if (MVT_STRINGA == pDest->type)
{
// If Writing Transmit (Write Header Name)
if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
{
// Write Name Into Data
CHECKHR(hr = HrWriteNameInDataA(pConvert, &rVariant, pDest));
}
// Is Equal to pszFree
else if (rVariant.rStringA.pszVal == pszFree)
{
// Copy Memory
CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
// Not a Copy
pDest->fCopy = FALSE;
// Don't Free pszFree
pszFree = NULL;
}
// Big Problem
else
Assert(FALSE);
}
// Big Problem
else
Assert(FALSE);
exit:
// Cleanup
SafeMemFree(pszFree);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringW_To_StringW
// --------------------------------------------------------------------------------
HRESULT StringW_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
MIMEVARIANT rVariant;
LPWSTR pszFree=NULL;
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
// Invalid Arg
if (ISVALIDSTRINGW(&pSource->rStringW) == FALSE)
return TrapError(E_INVALIDARG);
// Init pDest
if (MVT_STRINGW == pDest->type)
{
pDest->rStringW.pszVal = NULL;
pDest->rStringW.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
rVariant.type = MVT_STRINGW;
// Internat Conversion
CHECKHR(hr = Internat_StringW_To_StringW(pConvert, pSource, &rVariant, &pszFree));
// If Transmit, setup wrapinfo
if (ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT))
{
// WriteHeaderFormatW
CHECKHR(hr = HrWriteHeaderFormatW(pConvert, &rVariant, pDest));
}
// Wanted in a stream
else if (MVT_STREAM == pDest->type)
{
// No Stream...
if (NULL == pDest->pStream)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Write to the stream
CHECKHR(hr = pDest->pStream->Write(rVariant.rStringW.pszVal, rVariant.rStringW.cchVal, NULL));
}
// MVT_STRINGW
else if (MVT_STRINGW == pDest->type)
{
// If Writing Transmit (Write Header Name)
if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
{
CHECKHR(hr = HrWriteNameInDataW(pConvert, &rVariant, pDest));
}
// No Change
else if (rVariant.rStringW.pszVal == pSource->rStringW.pszVal)
{
// Copy
CHECKHR(hr = HrMimeVariantCopy(pConvert->dwFlags, &rVariant, pDest));
}
// Is Decoded Data
else if (rVariant.rStringW.pszVal == pszFree)
{
// Copy Memory
CopyMemory(pDest, &rVariant, sizeof(MIMEVARIANT));
// Not a Copy
pDest->fCopy = FALSE;
// Don't Free pszFree
pszFree = NULL;
}
// Problem
else
Assert(FALSE);
}
// Problem
else
Assert(FALSE);
exit:
// Cleanup
SafeMemFree(pszFree);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// StringW_To_Variant
// --------------------------------------------------------------------------------
HRESULT StringW_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pwsz;
LPSTR pszANSI=NULL;
MIMEVARIANT rVariant;
BYTE rgbScratch[255];
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_VARIANT);
Assert(!ISFLAGSET(pConvert->dwFlags, PDF_ENCODED) && !ISFLAGSET(pConvert->dwFlags, PDF_HEADERFORMAT));
// Init
ZeroMemory(&rVariant, sizeof(MIMEVARIANT));
// See If Symbol has a custom Translator...
if (ISTRIGGERED(pConvert->pSymbol, IST_STRINGW_TO_VARIANT))
{
// Call the Translator
CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_STRINGW_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
}
// Otherwise, use default converter
else
{
// Handle Variant Type
switch(pDest->rVariant.vt)
{
case VT_UI4:
// Strip Comments
if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
pSource = &rVariant;
// Convert to ulong
pDest->rVariant.ulVal = StrToUintW(pSource->rStringW.pszVal);
break;
case VT_I4:
// Strip Comments
if (SUCCEEDED(MimeVariantStripComments(pSource, &rVariant, rgbScratch, sizeof(rgbScratch))))
pSource = &rVariant;
// Convert to Long
pDest->rVariant.lVal = StrToIntW(pSource->rStringW.pszVal);
break;
case VT_FILETIME:
// Convert Unicode to ANSI
CHECKALLOC(pszANSI = PszToANSI(CP_ACP, pSource->rStringW.pszVal));
// String to FileTime
CHECKHR(hr = MimeOleInetDateToFileTime(pSource->rStringA.pszVal, &pDest->rVariant.filetime));
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
}
exit:
// Cleanup
SafeMemFree(pszANSI);
MimeVariantFree(&rVariant);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Variant_To_StringA
// --------------------------------------------------------------------------------
HRESULT Variant_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
CHAR sz[255];
MIMEVARIANT rValue;
// Invalid Arg
VCASSERTARGS(MVT_VARIANT, MVT_STRINGA);
// Init pDest
if (MVT_STRINGA == pDest->type)
{
pDest->rStringA.pszVal = NULL;
pDest->rStringA.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rValue, sizeof(MIMEVARIANT));
rValue.type = MVT_STRINGA;
// See If Symbol has a custom Translator...
if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_STRINGA))
{
// Call the Translator
CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_STRINGA, pConvert->dwFlags, pSource, &rValue));
}
// Otherwise, default translator
else
{
// Handle Variant Type
switch(pSource->rVariant.vt)
{
case VT_UI4:
rValue.rStringA.pszVal = sz;
rValue.rStringA.cchVal = wnsprintfA(rValue.rStringA.pszVal, ARRAYSIZE(sz), "%d", pSource->rVariant.ulVal);
break;
case VT_I4:
rValue.rStringA.pszVal = sz;
rValue.rStringA.cchVal = wnsprintfA(rValue.rStringA.pszVal, ARRAYSIZE(sz), "%d", pSource->rVariant.lVal);
break;
case VT_FILETIME:
CHECKHR(hr = MimeOleFileTimeToInetDate(&pSource->rVariant.filetime, sz, sizeof(sz)));
rValue.rStringA.pszVal = sz;
rValue.rStringA.cchVal = lstrlen(sz);
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
}
// VX_StringA_To_StringA
CHECKHR(hr = StringA_To_StringA(pConvert, &rValue, pDest));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Variant_To_StringW
// --------------------------------------------------------------------------------
HRESULT Variant_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pwszVal=NULL;
WCHAR wsz[255];
CHAR szData[CCHMAX_INTERNET_DATE];
MIMEVARIANT rValue;
// Invalid Arg
VCASSERTARGS(MVT_VARIANT, MVT_STRINGW);
// Init pDest
if (MVT_STRINGW == pDest->type)
{
pDest->rStringW.pszVal = NULL;
pDest->rStringW.cchVal = 0;
}
// Setup rVariant
ZeroMemory(&rValue, sizeof(MIMEVARIANT));
rValue.type = MVT_STRINGW;
// See If Symbol has a custom Translator...
if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_STRINGW))
{
// Call the Translator
CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_STRINGW, pConvert->dwFlags, pSource, &rValue));
}
// Otherwise, use default converter
else
{
// Handle Variant Type
switch(pSource->rVariant.vt)
{
case VT_UI4:
rValue.rStringW.pszVal = wsz;
rValue.rStringW.cchVal = wnsprintfW(rValue.rStringW.pszVal, ARRAYSIZE(wsz), L"%d", pSource->rVariant.ulVal);
break;
case VT_I4:
rValue.rStringW.pszVal = wsz;
rValue.rStringW.cchVal = wnsprintfW(rValue.rStringW.pszVal, ARRAYSIZE(wsz), L"%d", pSource->rVariant.lVal);
break;
case VT_FILETIME:
CHECKHR(hr = MimeOleFileTimeToInetDate(&pSource->rVariant.filetime, szData, sizeof(szData)));
CHECKALLOC(pwszVal = PszToUnicode(CP_ACP, szData));
rValue.rStringW.pszVal = pwszVal;
rValue.rStringW.cchVal = lstrlenW(pwszVal);
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
}
// VX_StringA_To_StringA
CHECKHR(hr = StringW_To_StringW(pConvert, &rValue, pDest));
exit:
// Cleanup
SafeMemFree(pwszVal);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Variant_To_Variant
// --------------------------------------------------------------------------------
HRESULT Variant_To_Variant(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_VARIANT, MVT_VARIANT);
// See If Symbol has a custom Translator...
if (ISTRIGGERED(pConvert->pSymbol, IST_VARIANT_TO_VARIANT))
{
// Call the Translator
CHECKHR(hr = CALLTRIGGER(pConvert->pSymbol, NULL, IST_VARIANT_TO_VARIANT, pConvert->dwFlags, pSource, pDest));
}
// Otherwise, use default converter
else
{
// Handle Variant Type
switch(pSource->rVariant.vt)
{
case VT_UI4:
switch(pDest->rVariant.vt)
{
case VT_UI4:
pDest->rVariant.ulVal = pSource->rVariant.ulVal;
break;
case VT_I4:
pDest->rVariant.lVal = (LONG)pSource->rVariant.ulVal;
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
break;
case VT_I4:
switch(pDest->rVariant.vt)
{
case VT_UI4:
pDest->rVariant.ulVal = (ULONG)pSource->rVariant.lVal;
break;
case VT_I4:
pDest->rVariant.lVal = pSource->rVariant.lVal;
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
break;
case VT_FILETIME:
switch(pDest->rVariant.vt)
{
case VT_FILETIME:
CopyMemory(&pDest->rVariant.filetime, &pSource->rVariant.filetime, sizeof(FILETIME));
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
break;
default:
hr = TrapError(MIME_E_VARTYPE_NO_CONVERT);
goto exit;
}
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrMimeVariantCopy
// --------------------------------------------------------------------------------
HRESULT HrMimeVariantCopy(DWORD dwFlags, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
Assert(pSource && pDest);
// CVF_NOALLOC
if (ISFLAGSET(dwFlags, CVF_NOALLOC))
{
// Just Copy It
CopyMemory(pDest, pSource, sizeof(MIMEVARIANT));
// Set fCopy so we don't free it
pDest->fCopy = TRUE;
}
// Allocate Memory
else
{
// Not a Copy
pDest->fCopy = FALSE;
// MVT_STRINGA
if (MVT_STRINGA == pSource->type)
{
// Validate
Assert(ISVALIDSTRINGA(&pSource->rStringA));
// Set Dest Type
pDest->type = MVT_STRINGA;
// Allocate Memory
CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(pSource->rStringA.cchVal + 1));
// Copy the memory
CopyMemory(pDest->rStringA.pszVal, pSource->rStringA.pszVal, pSource->rStringA.cchVal + 1);
// Return the Size
pDest->rStringA.cchVal = pSource->rStringA.cchVal;
}
// MVT_STRINGW
else if (MVT_STRINGW == pSource->type)
{
// Validate
Assert(ISVALIDSTRINGW(&pSource->rStringW));
// Set Dest Type
pDest->type = MVT_STRINGW;
// Compute CB
ULONG cb = ((pSource->rStringW.cchVal + 1) * sizeof(WCHAR));
// Allocate Memory
CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc(cb));
// Copy the memory
CopyMemory(pDest->rStringW.pszVal, pSource->rStringW.pszVal, cb);
// Return the Size
pDest->rStringW.cchVal = pSource->rStringW.cchVal;
}
// MVT_VARIANT
else if (MVT_VARIANT == pSource->type)
{
// Set Dest Type
pDest->type = MVT_VARIANT;
// Copy the Variant
CopyMemory(&pDest->rVariant, &pSource->rVariant, sizeof(PROPVARIANT));
}
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrWriteNameInDataA
// --------------------------------------------------------------------------------
HRESULT HrWriteNameInDataA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
// Generic STuff
pDest->fCopy = FALSE;
// pszNamed
DWORD cchSize = (pSource->rStringA.cchVal + 3 + pConvert->pSymbol->cchName);
CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(cchSize));
// Write the named header
pDest->rStringA.cchVal = wnsprintf(pDest->rStringA.pszVal, cchSize, "%s: %s", pConvert->pSymbol->pszName, pSource->rStringA.pszVal);
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrWriteNameInDataW
// --------------------------------------------------------------------------------
HRESULT HrWriteNameInDataW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
ULONG cb;
LPWSTR pszName=NULL;
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
// Generic STuff
pDest->fCopy = FALSE;
// Convert Name to Unicode
CHECKALLOC(pszName = PszToUnicode(CP_ACP, pConvert->pSymbol->pszName));
// Compute CB
cb = ((pSource->rStringW.cchVal + 3 + lstrlenW(pszName)) * sizeof(WCHAR));
// pszNamed
CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc(cb));
// Write the named header
pDest->rStringW.cchVal = wnsprintfW(pDest->rStringW.pszVal, (cb/sizeof(WCHAR)), L"%s: %s", pszName, pSource->rStringW.pszVal);
exit:
// Cleanup
SafeMemFree(pszName);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrWriteHeaderFormatA
// --------------------------------------------------------------------------------
HRESULT HrWriteHeaderFormatA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
// Locals
HRESULT hr=S_OK;
LPSTREAM pStream;
CByteStream cByteStream;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
// Generic Stuff
pDest->fCopy = FALSE;
// I need a stream to write to...
if (MVT_STREAM == pDest->type)
{
// Validate the stream
if (NULL == pDest->pStream)
{
hr = TrapError(E_INVALIDARG);
goto exit;
}
// Save the Stream
pStream = pDest->pStream;
}
// Otherwise, create my own stream
else
pStream = &cByteStream;
// If Writing Transmit (Write Header Name)
if (ISFLAGSET(pConvert->dwFlags, PDF_NAMEINDATA))
{
// Write the header name
CHECKHR(hr = pStream->Write(pConvert->pSymbol->pszName, pConvert->pSymbol->cchName, NULL));
// Write Colon
CHECKHR(hr = pStream->Write(c_szColonSpace, lstrlen(c_szColonSpace), NULL));
}
// If not rfc1522 Encoded
if (FALSE == ISFLAGSET(pConvert->dwState, PRSTATE_RFC1522))
{
// PID_HDR_CNTID
if (PID_HDR_CNTID == pConvert->pSymbol->dwPropId)
{
// If not a < yet...
if ('<' != pSource->rStringA.pszVal[0])
{
// Write it
CHECKHR(hr = pStream->Write(c_szEmailStart, lstrlen(c_szEmailStart), NULL));
}
// Write the data
CHECKHR(hr = pStream->Write(pSource->rStringA.pszVal, pSource->rStringA.cchVal, NULL));
// >
if ('>' != pSource->rStringA.pszVal[pSource->rStringA.cchVal - 1])
{
// Write it
CHECKHR(hr = pStream->Write(c_szEmailEnd, lstrlen(c_szEmailEnd), NULL));
}
// Write CRLF
CHECKHR(hr = pStream->Write(c_szCRLF, lstrlen(c_szCRLF), NULL));
}
// Do a wrap text
else
{
// Wrap pszData to the stream
CHECKHR(hr = MimeOleWrapHeaderText(CP_USASCII, pConvert->pOptions->cbMaxLine, pSource->rStringA.pszVal, pSource->rStringA.cchVal, pStream));
}
}
// Otherwise
else
{
// Write the data
CHECKHR(hr = pStream->Write(pSource->rStringA.pszVal, pSource->rStringA.cchVal, NULL));
// Write CRLF
CHECKHR(hr = pStream->Write(c_szCRLF, lstrlen(c_szCRLF), NULL));
}
// MVT_STRINGA
if (MVT_STRINGA == pDest->type)
{
// pStream better be the byte stream
Assert(pStream == &cByteStream);
// Get string from stream...
CHECKHR(hr = cByteStream.HrAcquireStringA(&pDest->rStringA.cchVal, &pDest->rStringA.pszVal, ACQ_DISPLACE));
}
else
Assert(MVT_STREAM == pDest->type);
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrWriteHeaderFormatW
// --------------------------------------------------------------------------------
HRESULT HrWriteHeaderFormatW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource, LPMIMEVARIANT pDest)
{
return TrapError(MIME_E_VARTYPE_NO_CONVERT);
}
// --------------------------------------------------------------------------------
// Internat_StringA_To_StringA
// --------------------------------------------------------------------------------
HRESULT Internat_StringA_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
LPMIMEVARIANT pDest, LPSTR *ppszFree)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGA);
// Init
pDest->rStringA.pszVal = NULL;
*ppszFree = NULL;
// Internat
if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
{
// Encoded...
if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
{
// Save no encode
if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
{
// Decode the Property
if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringA.pszVal;
}
}
// Decoded
else if (IET_ENCODED == pConvert->ietSource)
{
// Decode Property
if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringA.pszVal;
}
}
// Default
if (NULL == pDest->rStringA.pszVal)
{
// Check State
Assert(NULL == *ppszFree);
// Copy It
pDest->rStringA.pszVal = pSource->rStringA.pszVal;
pDest->rStringA.cchVal = pSource->rStringA.cchVal;
// pDest is a copy
pDest->fCopy = TRUE;
}
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Internat_StringW_To_StringW
// --------------------------------------------------------------------------------
HRESULT Internat_StringW_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
LPMIMEVARIANT pDest, LPWSTR *ppszFree)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_STRINGW);
// Init
pDest->rStringW.pszVal = NULL;
*ppszFree = NULL;
// Internat
if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
{
// Encoded...
if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
{
// Save no encode
if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
{
// Decode the Property
if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringW.pszVal;
}
}
// Decoded
else if (IET_ENCODED == pConvert->ietSource)
{
// Decode Property
if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringW.pszVal;
}
}
// Default
if (NULL == pDest->rStringW.pszVal)
{
// Check State
Assert(NULL == *ppszFree);
// Copy It
pDest->rStringW.pszVal = pSource->rStringW.pszVal;
pDest->rStringW.cchVal = pSource->rStringW.cchVal;
// Its a copy
pDest->fCopy = TRUE;
}
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Internat_StringA_To_StringW
// --------------------------------------------------------------------------------
HRESULT Internat_StringA_To_StringW(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
LPMIMEVARIANT pDest, LPWSTR *ppszFree)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_STRINGA, MVT_STRINGW);
// Init
pDest->rStringW.pszVal = NULL;
*ppszFree = NULL;
// Internat
if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
{
// Encoded...
if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
{
// Save no encode
if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
{
// Decode the Property
if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringW.pszVal;
}
}
// Decoded
else if (IET_ENCODED == pConvert->ietSource)
{
// Decode Property
if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringW.pszVal;
}
}
// Simple Conversion to Unicode
if (NULL == pDest->rStringW.pszVal)
{
// Check State
Assert(NULL == *ppszFree);
// HrMultiByteToWideChar
CHECKHR(hr = g_pInternat->HrMultiByteToWideChar(pConvert->pCharset->cpiWindows, &pSource->rStringA, &pDest->rStringW));
// Save Charset/Encoding
pDest->fCopy = FALSE;
// Save pwszWide
*ppszFree = pDest->rStringW.pszVal;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// Internat_StringW_To_StringA
// --------------------------------------------------------------------------------
HRESULT Internat_StringW_To_StringA(LPVARIANTCONVERT pConvert, LPMIMEVARIANT pSource,
LPMIMEVARIANT pDest, LPSTR *ppszFree)
{
// Locals
HRESULT hr=S_OK;
// Invalid Arg
VCASSERTARGS(MVT_STRINGW, MVT_STRINGA);
// Init
pDest->rStringA.pszVal = NULL;
*ppszFree = NULL;
// Internat
if (ISFLAGSET(pConvert->pSymbol->dwFlags, MPF_INETCSET))
{
// Encoded...
if (ISFLAGSET(pConvert->dwFlags, PDF_ENCODED))
{
// Save no encode
if (!ISFLAGSET(pConvert->dwState, PRSTATE_SAVENOENCODE))
{
// Decode the Property
if (SUCCEEDED(g_pInternat->HrEncodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringA.pszVal;
}
}
// Decoded
else if (IET_ENCODED == pConvert->ietSource)
{
// Decode Property
if (SUCCEEDED(g_pInternat->HrDecodeProperty(pConvert, pSource, pDest)))
*ppszFree = pDest->rStringA.pszVal;
}
}
// Simple Conversion to Unicode
if (NULL == pDest->rStringA.pszVal)
{
// Check State
Assert(NULL == *ppszFree);
// HrMultiByteToWideChar
CHECKHR(hr = g_pInternat->HrWideCharToMultiByte(pConvert->pCharset->cpiWindows, &pSource->rStringW, &pDest->rStringA));
// Save Charset/Encoding
pDest->fCopy = FALSE;
// Save pwszWide
*ppszFree = pDest->rStringA.pszVal;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// MimeVariantFree
// --------------------------------------------------------------------------------
void MimeVariantFree(LPMIMEVARIANT pVariant)
{
// Invalid Arg
Assert(pVariant);
// If not a copy
if (FALSE == pVariant->fCopy)
{
// MVT_STRINGA
if (MVT_STRINGA == pVariant->type && NULL != pVariant->rStringA.pszVal)
g_pMalloc->Free(pVariant->rStringA.pszVal);
// MVT_STRINGW
else if (MVT_STRINGW == pVariant->type && NULL != pVariant->rStringW.pszVal)
g_pMalloc->Free(pVariant->rStringW.pszVal);
}
// Zero Out the Structure
ZeroMemory(pVariant, sizeof(MIMEVARIANT));
}
// ---------------------------------------------------------------------------------------
// MimeVariantCleanupFileName
// ---------------------------------------------------------------------------------------
void MimeVariantCleanupFileName(CODEPAGEID codepage, LPMIMEVARIANT pVariant)
{
// Locals
ULONG i=0;
// MVT_STRINGA
if (MVT_STRINGA == pVariant->type && ISVALIDSTRINGA(&pVariant->rStringA))
{
// Cleanup
pVariant->rStringA.cchVal = CleanupFileNameInPlaceA(codepage, pVariant->rStringA.pszVal);
}
// MVT_STRINGW
else if (MVT_STRINGW == pVariant->type && ISVALIDSTRINGW(&pVariant->rStringW))
{
// Cleanup
pVariant->rStringW.cchVal = CleanupFileNameInPlaceW(pVariant->rStringW.pszVal);
}
// Hmmm....
else
Assert(FALSE);
// Done
return;
}
// ---------------------------------------------------------------------------------------
// MimeVariantStripComments
// ---------------------------------------------------------------------------------------
HRESULT MimeVariantStripComments(LPMIMEVARIANT pSource, LPMIMEVARIANT pDest, LPBYTE pbScratch, ULONG cbScratch)
{
// Locals
HRESULT hr=S_OK;
ULONG cchVal=0;
BOOL fInQuoted=FALSE;
ULONG cNested=0;
// Init
ZeroMemory(pDest, sizeof(MIMEVARIANT));
// MVT_STRINGA
if (MVT_STRINGA == pSource->type && ISVALIDSTRINGA(&pSource->rStringA))
{
// Locals
LPSTR psz;
// Setup pDest
pDest->type = MVT_STRINGA;
// Dup It
if (pSource->rStringA.cchVal + 1 <= cbScratch)
{
pDest->fCopy = TRUE;
pDest->rStringA.pszVal = (LPSTR)pbScratch;
}
// Otherwise, allocate memory
else
{
// Allocate
CHECKALLOC(pDest->rStringA.pszVal = (LPSTR)g_pMalloc->Alloc(pSource->rStringA.cchVal + 1));
}
// Setup Loop
psz = pSource->rStringA.pszVal;
while(*psz)
{
// If lead byte, skip it, its leagal
if (IsDBCSLeadByte(*psz))
{
pDest->rStringA.pszVal[cchVal++] = *psz++;
pDest->rStringA.pszVal[cchVal++] = *psz++;
}
// Starting Comment
else if ('(' == *psz && !fInQuoted)
{
cNested++;
psz++;
}
// Ending Comment
else if (')' == *psz && !fInQuoted)
{
cNested--;
psz++;
}
// Otherwise, if not nested, append
else if (!cNested)
{
// Copy the Char
pDest->rStringA.pszVal[cchVal++] = *psz++;
// Check for Quote
if ('\"' == *psz)
fInQuoted = (fInQuoted) ? FALSE : TRUE;
}
// Skip Char
else
psz++;
}
// No Change
if (cchVal == pSource->rStringA.cchVal)
{
hr = E_FAIL;
goto exit;
}
// Null It
pDest->rStringA.pszVal[cchVal] = '\0';
}
// MVT_STRINGW
else if (MVT_STRINGW == pSource->type && ISVALIDSTRINGW(&pSource->rStringW))
{
// Locals
LPWSTR pwsz;
// Setup pDest
pDest->type = MVT_STRINGW;
// Dup It
if ((pSource->rStringW.cchVal + 1) * sizeof(WCHAR) <= cbScratch)
{
pDest->fCopy = TRUE;
pDest->rStringW.pszVal = (LPWSTR)pbScratch;
}
// Otherwise, allocate memory
else
{
// Dup It
CHECKALLOC(pDest->rStringW.pszVal = (LPWSTR)g_pMalloc->Alloc((pSource->rStringW.cchVal + 1) * sizeof(WCHAR)));
}
// Setup Loop
pwsz = pSource->rStringW.pszVal;
while(*pwsz)
{
// Starting Comment
if (L'(' == *pwsz && !fInQuoted)
{
cNested++;
pwsz++;
}
// Ending Comment
if (L')' == *pwsz && !fInQuoted)
{
cNested--;
pwsz++;
}
// Otherwise, if not nested, append
else if (!cNested)
{
// Copy the Character
pDest->rStringW.pszVal[cchVal++] = *pwsz++;
// Check for Quote
if (L'\"' == *pwsz)
fInQuoted = (fInQuoted) ? FALSE : TRUE;
}
// Skip Char
else
pwsz++;
}
// No Change
if (cchVal == pSource->rStringW.cchVal)
{
hr = E_FAIL;
goto exit;
}
// Null It
pDest->rStringW.pszVal[cchVal] = L'\0';
}
// Hmmm....
else
Assert(FALSE);
exit:
// Cleanup
if (FAILED(hr))
MimeVariantFree(pDest);
// Done
return hr;
}