Windows-Server-2003/inetsrv/pop3/admin/snapin/streamio.cpp

239 lines
6.7 KiB
C++

// stream i/o functions
#include "stdafx.h"
#include <comutil.h>
#include <memory>
// Used Defines
#define THROW_ON_FAILURE(hr) if (FAILED(hr)) _com_issue_error(hr);
#define THROW_ERROR(hr) _com_issue_error(hr);
/*+-------------------------------------------------------------------------*
* ReadScalar
*
* Reads a scalar value from a stream.
*--------------------------------------------------------------------------*/
template<class T>
static IStream& ReadScalar (IStream& stm, T& t)
{
ULONG cbActuallyRead;
HRESULT hr = stm.Read (&t, sizeof (t), &cbActuallyRead);
THROW_ON_FAILURE(hr);
if (cbActuallyRead != sizeof (t))
_com_issue_error (E_FAIL);
return (stm);
}
/*+-------------------------------------------------------------------------*
* WriteScalar
*
* Writes a scalar value to a stream.
*--------------------------------------------------------------------------*/
template<class T>
static IStream& WriteScalar (IStream& stm, const T& t)
{
ULONG cbActuallyWritten;
HRESULT hr = stm.Write (&t, sizeof (t), &cbActuallyWritten);
THROW_ON_FAILURE(hr);
if (cbActuallyWritten != sizeof (t))
THROW_ERROR(E_FAIL);
return (stm);
}
//----------------------------------------------------------------
// Define by-value stream operators
//----------------------------------------------------------------
#define DefineScalarStreamOperators(scalar_type) \
IStream& operator>> (IStream& stm, scalar_type& t) \
{ return (ReadScalar (stm, t)); } \
IStream& operator<< (IStream& stm, scalar_type t) \
{ return (WriteScalar (stm, t)); }
DefineScalarStreamOperators ( bool);
DefineScalarStreamOperators ( char);
DefineScalarStreamOperators (unsigned char);
DefineScalarStreamOperators ( short);
DefineScalarStreamOperators (unsigned short);
DefineScalarStreamOperators ( int);
DefineScalarStreamOperators (unsigned int);
DefineScalarStreamOperators ( long);
DefineScalarStreamOperators (unsigned long);
//----------------------------------------------------------------
// Define by-value stream operators
//----------------------------------------------------------------
#define DefineScalarStreamOperatorsByRef(scalar_type) \
IStream& operator>> (IStream& stm, scalar_type& t) \
{ return (ReadScalar (stm, t)); } \
IStream& operator<< (IStream& stm, const scalar_type& t) \
{ return (WriteScalar (stm, t)); }
DefineScalarStreamOperatorsByRef(CLSID);
DefineScalarStreamOperatorsByRef(FILETIME);
/*+-------------------------------------------------------------------------*
* ReadString
*
* Reads a std::basic_string of char type CH from a stream. The string should
* have been written with a DWORD character count preceding an array of
* characters that is not NULL-terminated.
*--------------------------------------------------------------------------*/
template<class CH>
static IStream& ReadString (IStream& stm, std::basic_string<CH>& str)
{
/*
* read the length
*/
DWORD cch;
stm >> cch;
/*
* allocate a buffer for the characters
*/
std::auto_ptr<CH> spBuffer (new (std::nothrow) CH[cch + 1]);
CH* pBuffer = spBuffer.get();
if (pBuffer == NULL)
THROW_ERROR(E_OUTOFMEMORY);
/*
* read the characters
*/
ULONG cbActuallyRead;
const ULONG cbToRead = cch * sizeof (CH);
HRESULT hr = stm.Read (pBuffer, cbToRead, &cbActuallyRead);
THROW_ON_FAILURE(hr);
if (cbToRead != cbActuallyRead)
THROW_ERROR(E_FAIL);
/*
* terminate the character array and assign it to the string
*/
pBuffer[cch] = 0;
/*
* assign it to the string (clear the string first to work around
* the bug described in KB Q172398)
*/
str.erase();
str = pBuffer;
return (stm);
}
/*+-------------------------------------------------------------------------*
* ReadString for byte_string
*
* Specialization of ReadString for a string of bytes which may contain NULLs.
* he string should have been written with a DWORD character count preceding
* an array of characters that is not NULL-terminated.
*--------------------------------------------------------------------------*/
static IStream& ReadString (IStream& stm, std::basic_string<BYTE>& str)
{
/*
* read the length
*/
DWORD cch;
stm >> cch;
if (cch == 0)
{
str.erase();
}
else
{
/*
* allocate a buffer for the characters
*/
std::auto_ptr<BYTE> spBuffer (new (std::nothrow) BYTE[cch]);
BYTE* pBuffer = spBuffer.get();
if (pBuffer == NULL)
THROW_ERROR(E_OUTOFMEMORY);
/*
* read the characters
*/
ULONG cbActuallyRead;
const ULONG cbToRead = cch;
HRESULT hr = stm.Read (pBuffer, cbToRead, &cbActuallyRead);
THROW_ON_FAILURE(hr);
if (cbToRead != cbActuallyRead)
THROW_ERROR(E_FAIL);
/*
* assign it to the string (clear the string first to work around
* the bug described in KB Q172398)
*/
str.erase();
str.assign(pBuffer, cch);
}
return (stm);
}
/*+-------------------------------------------------------------------------*
* WriteString
*
* Writes a std::basic_string of char type CH to a stream. The string is
* written with a DWORD character count preceding an array of characters that
* is not NULL-terminated.
*--------------------------------------------------------------------------*/
template<class CH>
static IStream& WriteString (IStream& stm, const std::basic_string<CH>& str)
{
/*
* write the length
*/
DWORD cch = str.length();
stm << cch;
if (cch > 0)
{
/*
* write the characters
*/
ULONG cbActuallyWritten;
const ULONG cbToWrite = cch * sizeof (CH);
HRESULT hr = stm.Write (str.data(), cbToWrite, &cbActuallyWritten);
THROW_ON_FAILURE(hr);
if (cbToWrite != cbActuallyWritten)
THROW_ERROR(E_FAIL);
}
return (stm);
}
//-----------------------------------------------------------------
// Define basic string stream operators
//-----------------------------------------------------------------
#define DefineStringStreamOperators(string_type) \
IStream& operator>> (IStream& stm, string_type& str) \
{ return (ReadString (stm, str)); } \
IStream& operator<< (IStream& stm, const string_type& str) \
{ return (WriteString (stm, str)); }
DefineStringStreamOperators(tstring);
DefineStringStreamOperators(byte_string);