// --toupper.c------------------------------------------------------------------
//
// Converter that renders a message body to an attachment
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
//
// -----------------------------------------------------------------------------
#define _MEMLOG_H // skip mem logging stuff until it works in UNICODE.
#define EDK_USES_IID
#include "edk.h"
#include "vsop.h"
#include "toupper.chk"
//$--HrCnvQueryCapability-------------------------------------------------------
//
// DESCRIPTION: Routine called by the conversion engine to determine whether the converter
// can handle a particular message.
//
// INPUT:
// pszOptions -- options passed from conversion
// pszClass -- class of object to be converted
// pContent -- object oto be converted.
// pEnv -- environment for conversion
//
// OUTPUT: pfAmCandidate -- TRUE if can convert, FALSE otherwise
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input
//
// -----------------------------------------------------------------------------
static HRESULT HrCnvQueryCapability(
IN LPCWSTR pszOptions, // options passed from conversion engine
IN LPCWSTR pszClass, // class of object to be converted.
IN PVOID pContent, // object to be covnerted.
IN PEDKCNVENV pEnv, // environment for conversion.
OUT BOOL * pfAmCandidate) // can convert?
{
HRESULT hr = NOERROR; // return code
DEBUGPRIVATE("HrCnvQueryCapability()\n");
// check input parameters
hr = CHK_HrCnvQueryCapability(pszOptions, pszClass, pContent,
pEnv, pfAmCandidate);
if ( FAILED(hr) )
{
RETURN(hr);
}
*pfAmCandidate = TRUE ; // yes, we can process it.
RETURN(hr) ;
}
//$--HrConvertStreamToUpperCase-----------------------------------------------
//
// DESCRIPTION: Convert data in input stream to upper-case
// equivalent in output stream.
//
// INPUT: lpStreamIn -- input stream to convert
// lpStreamOut -- output stream to convert to
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input,
// E_FAIL otherwise
//
// -----------------------------------------------------------------------------
static HRESULT HrConvertStreamToUpperCase(
IN LPSTREAM lpStreamIn, // input stream
IN LPSTREAM lpStreamOut) // output stream
{
// maximum # characters to read at a time
#defineMAX_CHARS_READ8192
HRESULT hr = NOERROR;
ULONG cbRead = 0; // # bytes read
DWORDcchUpper=0;// # chars converted to upper case
const ULONG cbWanted = 8192 * sizeof(CHAR); // # bytes wanted
CHARrgchBuffer[MAX_CHARS_READ]="";// text buffer
DEBUGPRIVATE("HrConvertStreamToUpperCase()\n");
// check input parameters
hr = CHK_HrConvertStreamToUpperCase(lpStreamIn, lpStreamOut);
if ( FAILED(hr) )
{
RETURN(hr);
}
while ( TRUE )
{
// Read a block of characters from the input stream
// & write the uppercase version to the output
// stream.
hr = OLECALL(lpStreamIn)->Read(
lpStreamIn, // object pointer
rgchBuffer, // data buffer
cbWanted, // # bytes to read
&cbRead); // # bytes read
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Test for end of data
if ( cbRead == 0 )
{
// we are done.
goto cleanup;
}
ASSERTERROR(cbRead <= cbWanted, "Bad cbRead");
// convert character buffer to upper case
cchUpper = CharUpperBuffA(
rgchBuffer,// character buffer
cbRead/sizeof(CHAR));// # characters in buffer
ASSERTERROR((cchUpper == cbRead * sizeof(CHAR)), "Bad cchUpper");
// Write the upper-cased character to the output
// stream
hr = OLECALL(lpStreamOut)->Write(
lpStreamOut, // object pointer
rgchBuffer, // upper cased data
cbRead, // # bytes to write
NULL); // don't care
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
} // end while
// we are done
cleanup:
RETURN(hr);
}
//$--HrWriteToStreamA-----------------------------------------------------------
//
// DESCRIPTION: Write an ANSI string to a stream.
//
// INPUT: lpStream -- stream to write to
// lpsz -- string to write to stream
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input
// E_FAIL otherwise.
//
// -----------------------------------------------------------------------------
static HRESULT HrWriteToStreamA( // RETURNS: HRESULT
IN LPSTREAM lpStream, // stream to write to.
IN LPSTR lpsz) // ANSI string to write.
{
HRESULT hr = NOERROR; // return code
ULONG ulBytesWritten = 0 ;
ULONG ulBytesToWrite = 0;
DEBUGPRIVATE("HrWriteToStreamA()\n");
// check input parameters
hr = CHK_HrWriteToStreamA(lpStream, lpsz);
if ( FAILED(hr) )
{
RETURN(hr);
}
ulBytesToWrite = lstrlenA(lpsz) * sizeof(CHAR) ;
hr = OLECALL(lpStream)->Write(lpStream, lpsz, ulBytesToWrite, &ulBytesWritten);
if ( FAILED(hr) || (ulBytesWritten != ulBytesToWrite) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--HrWriteToStreamW-----------------------------------------------------------
//
// DESCRIPTION: Write a wide string to a stream.
//
// INPUT: lpStream -- stream to write to
// lpsz -- string to write
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input
// E_FAIL otherwise.
//
// -----------------------------------------------------------------------------
static HRESULT HrWriteToStreamW( // RETURNS: HRESULT
IN LPSTREAM lpStream, // stream to write to.
IN LPWSTR lpsz) // wide string to write.
{
HRESULT hr = NOERROR; // return code
ULONG ulBytesWritten = 0 ;
ULONG ulBytesToWrite = 0;
DEBUGPRIVATE("HrWriteToStreamW()\n");
// Check input parameters
hr = CHK_HrWriteToStreamW(lpStream, lpsz);
if ( FAILED(hr) )
{
RETURN(hr);
}
ulBytesToWrite = lstrlenW(lpsz) * sizeof(WCHAR) ;
hr = OLECALL(lpStream)->Write(lpStream, lpsz, ulBytesToWrite, &ulBytesWritten);
if ( FAILED(hr) || (ulBytesWritten != ulBytesToWrite) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--HrCnvConvert---------------------------------------------------------------
//
// DESCRIPTION: Perform the conversion.
//
// INPUT:
// pszOptions -- options (may be null)
// pszClass -- object class to be converted
// pContent -- objec to convert (GW message envelope pointer)
// pEnv -- environment for conversion
// pContentOut -- converted object (stream pointer)
//
// OUTPUT:
// pcr -- result of conversion
//
// RETURNS: HRESULT -- NOERROR if successful,
// E_INVALIDARG if bad input,
// E_FAIL otherwise.
//
// -----------------------------------------------------------------------------
static HRESULT HrCnvConvert(
IN LPCWSTR pszOptions, // options.
IN LPCWSTR pszClass, // object class to be converted.
IN PVOID pContent, // object to be covnerted.
IN PVOID pContentOut, // where to put the result.
IN PEDKCNVENV pEnv, // environment for conversion.
OUT EDKCNVRES * pcr) // result of conversion
{
HRESULT hr = NOERROR;
LPMESSAGE pEnvelope = NULL; // gateway message envelope pointer
LPATTACH pAttach = NULL; // envelope's attachment
LPMESSAGE pMessage = NULL; // content is an IMessage.
LPSTREAM lpStream = NULL;// output stream pointer
PVIRTUALSTREAMONPROPERTYpStrmBody= NULL;// buffered body text stream
DEBUGPRIVATE("HrCnvConvert()\n");
// check input parameters
hr = CHK_HrCnvConvert(pszOptions, pszClass, pContent,
pContentOut, pEnv, pcr);
if ( FAILED(hr) )
{
RETURN(hr);
}
// The input is a gateway message envelope pointer
pEnvelope = (LPMESSAGE) pContent;
// The output is a stream pointer.
lpStream = (LPSTREAM) pContentOut;
// Get the envelope's content.
hr = MAPICALL(pEnvelope)->OpenAttach(
pEnvelope, // message envelope pointer
0, // attachment number
NULL, // interface ID reference
MAPI_DEFERRED_ERRORS, // MAPI flags
&pAttach); // pointer to attachment pointer
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(!FBadUnknown(pAttach), "Bad lpAttach");
// Open a message interface on the attachment.
hr = MAPICALL(pAttach)->OpenProperty(
pAttach, // attachment pointer
PR_ATTACH_DATA_OBJ, // property tag
&IID_IMessage, // interface ID reference
0, // interface flags
MAPI_DEFERRED_ERRORS, // MAPI flags
(LPUNKNOWN *) &pMessage); // message pointer pointer
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ASSERTERROR(!FBadUnknown(pMessage), "Bad pMessage");
//
// Write a header to the the lpStream.
//
hr = HrWriteToStreamA(lpStream, "Message body follows:\r\n") ;
if (FAILED(hr))
{
goto cleanup ;
}
//
// Get a buffered stream on the ASCII body of the message.from the PR_BODY
// property. (We really want PR_BODY for this
// sample, since we want to print out a human-readable
// body text.)
hr = HrOpenVirtualStreamOnProperty(
(LPMAPIPROP) pMessage,// object pointer
PR_BODY_A,// property tag
MAPI_DEFERRED_ERRORS,// reduces RPCs
&pStrmBody);// buffered body stream pointer
if (SUCCEEDED(hr))
{
ASSERT_IUNKNOWN_PTR(pStrmBody, "Bad pStrmBody");
//
// There was a body.
//
//
// Convert the message to upper case.
//
hr = HrConvertStreamToUpperCase(
(LPSTREAM) pStrmBody, // buffered input stream
lpStream); // output stream
if ( FAILED(hr) )
{
goto cleanup;
}
}
else if (hr == MAPI_E_NOT_FOUND)
{
//
// No body. Put in a fake body.
// write fake body to stream
hr = HrWriteToStreamA(
lpStream,
"No Body") ;
if (FAILED(hr))
{
goto cleanup ;
}
hr = HR_LOG(NOERROR);
}
else
{
//
// Other error, die.
//
hr = HR_LOG(E_FAIL);
goto cleanup ;
}
// Commit changes to the stream.
hr = OLECALL(lpStream)->Commit(
lpStream, // stream pointer
STGC_DEFAULT); // commit flags
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// We're done. Tell the converter we did OK.
//
*pcr = GCR_OK ;
cleanup:
// Release MAPI objects.
ULRELEASE(pMessage);
ULRELEASE(pAttach);
ULRELEASE(pStrmBody);
RETURN(hr) ;
}
// structure that points to all routines exported by this converter.
static CONVDLLVECT cdExportVector =
{
1,
HrCnvQueryCapability,
HrCnvConvert
} ;
//$--HrGetExportVector---------------------------------------------------------
//
// DESCRIPTION: Called by conversion engine to get the vector of conversion entry points.
//
// OUTPUT: ppConvDLLVect -- pointer to conversion vector structure
//
// -----------------------------------------------------------------------------
extern HRESULT HrGetExportVector( // RETURNS: HRESULT
IN DWORD dwVersionRequired, // desired conversion DLL version number
OUT PCONVDLLVECT FAR * ppConvDLLVect) // pointer to conversion vector structure
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrGetExportVector()\n");
// check input parameters
hr = CHK_HrGetExportVector(dwVersionRequired, ppConvDLLVect);
if ( FAILED(hr) )
{
RETURN(hr);
}
*ppConvDLLVect = &cdExportVector;
RETURN(hr);
}