WindowsXP-SP1/admin/activec/core/stgio.cpp
2020-09-30 16:53:49 +02:00

306 lines
9.6 KiB
C++

/*--------------------------------------------------------------------------*
*
* Microsoft Windows
* Copyright (C) Microsoft Corporation, 1992 - 1999
*
* File: stgio.h
*
* Contents: Interface file structured storage I/O utilities
*
* History: 25-Jun-98 jeffro Created
*
*--------------------------------------------------------------------------*/
#include "stgio.h"
#include "stddbg.h"
#include "macros.h"
#include <comdef.h>
#include <tchar.h>
/*+-------------------------------------------------------------------------*
* 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_FAIL (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_FAIL (hr);
if (cbActuallyWritten != sizeof (t))
_com_issue_error (E_FAIL);
return (stm);
}
/*+-------------------------------------------------------------------------*
* ReadString
*
* Reads a std::basic_string 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 E, class Tr, class A>
static IStream& ReadString (IStream& stm, std::basic_string<E,Tr,A>& str)
{
/*
* read the length
*/
DWORD cch;
stm >> cch;
/*
* allocate a buffer for the characters
*/
std::auto_ptr<E> spBuffer (new (std::nothrow) E[cch + 1]);
E* pBuffer = spBuffer.get();
if (pBuffer == NULL)
_com_issue_error (E_OUTOFMEMORY);
/*
* read the characters
*/
ULONG cbActuallyRead;
const ULONG cbToRead = cch * sizeof (E);
HRESULT hr = stm.Read (pBuffer, cbToRead, &cbActuallyRead);
THROW_ON_FAIL (hr);
if (cbToRead != cbActuallyRead)
_com_issue_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);
}
/*+-------------------------------------------------------------------------*
* WriteString
*
* Writes a std::basic_string to a stream. The string is written with a
* DWORD character count preceding an array of characters that is not
* NULL-terminated.
*--------------------------------------------------------------------------*/
template<class E, class Tr, class A>
static IStream& WriteString (IStream& stm, const std::basic_string<E,Tr,A>& str)
{
/*
* write the length
*/
DWORD cch = str.length();
stm << cch;
if (cch > 0)
{
/*
* write the characters
*/
ULONG cbActuallyWritten;
const ULONG cbToWrite = cch * sizeof (E);
HRESULT hr = stm.Write (str.data(), cbToWrite, &cbActuallyWritten);
THROW_ON_FAIL (hr);
if (cbToWrite != cbActuallyWritten)
_com_issue_error (E_FAIL);
}
return (stm);
}
/*+-------------------------------------------------------------------------*
* operator<<, operator>>
*
* Stream insertion and extraction operators for various types
*--------------------------------------------------------------------------*/
#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)); }
#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)); }
DefineScalarStreamOperators (bool);
DefineScalarStreamOperators ( char);
DefineScalarStreamOperators (unsigned char);
DefineScalarStreamOperators ( short);
DefineScalarStreamOperators (unsigned short);
DefineScalarStreamOperators ( int);
DefineScalarStreamOperators (unsigned int);
DefineScalarStreamOperators ( long);
DefineScalarStreamOperators (unsigned long);
DefineScalarStreamOperators ( __int64);
DefineScalarStreamOperators (unsigned __int64);
DefineScalarStreamOperators (float);
DefineScalarStreamOperators (double);
DefineScalarStreamOperators (long double);
DefineScalarStreamOperatorsByRef (CLSID);
IStream& operator>> (IStream& stm, std::string& str)
{ return (ReadString (stm, str)); }
IStream& operator<< (IStream& stm, const std::string& str)
{ return (WriteString (stm, str)); }
IStream& operator>> (IStream& stm, std::wstring& str)
{ return (ReadString (stm, str)); }
IStream& operator<< (IStream& stm, const std::wstring& str)
{ return (WriteString (stm, str)); }
/*+-------------------------------------------------------------------------*
* ReadScalarVector
*
* Reads an entire vector collection of scalar types (written by
* insert_collection) from an IStream.
*--------------------------------------------------------------------------*/
template<class T>
static void ReadScalarVector (IStream* pstm, std::vector<T>& v)
{
/*
* clear out the current container
*/
v.clear();
/*
* read the number of items
*/
DWORD cItems;
*pstm >> cItems;
if (cItems > 0)
{
/*
* allocate a buffer for the elements
*/
std::auto_ptr<T> spBuffer (new (std::nothrow) T[cItems]);
T* pBuffer = spBuffer.get();
if (pBuffer == NULL)
_com_issue_error (E_OUTOFMEMORY);
/*
* read the elements
*/
ULONG cbActuallyRead;
const ULONG cbToRead = cItems * sizeof (T);
HRESULT hr = pstm->Read (pBuffer, cbToRead, &cbActuallyRead);
THROW_ON_FAIL (hr);
if (cbToRead != cbActuallyRead)
_com_issue_error (E_FAIL);
/*
* assign the elements to the vector
*/
v.assign (pBuffer, pBuffer + cItems);
}
}
/*+-------------------------------------------------------------------------*
* WriteScalarVector
*
* Writes an entire vector of scalar types to an IStream. Note that this
* code assumes that vectors store their elements sequentially.
*--------------------------------------------------------------------------*/
template<class T>
static void WriteScalarVector (IStream* pstm, const std::vector<T>& v)
{
/*
* write the size
*/
DWORD cItems = v.size();
*pstm << cItems;
if (cItems > 0)
{
/*
* write the elements
*/
ULONG cbActuallyWritten;
const ULONG cbToWrite = cItems * sizeof (T);
HRESULT hr = pstm->Write (v.begin(), cbToWrite, &cbActuallyWritten);
THROW_ON_FAIL (hr);
if (cbToWrite != cbActuallyWritten)
_com_issue_error (E_FAIL);
}
}
/*+-------------------------------------------------------------------------*
* extract_vector (specialization for std::vector<scalar>)
* Efficiently extracts an entire vector collection of scalar types
* (written by insert_collection) from an IStream.
*
* insert_collection (specializations for std::vector<scalar>)
* Efficiently inserts an entire vector of scalar types into an IStream.
*--------------------------------------------------------------------------*/
#define DefineScalarVectorStreamFunctions(scalar_type) \
void extract_vector (IStream* pstm, std::vector<scalar_type>& v) \
{ ReadScalarVector (pstm, v); } \
void insert_collection (IStream* pstm, const std::vector<scalar_type>& v)\
{ WriteScalarVector (pstm, v); }
DefineScalarVectorStreamFunctions (bool);
DefineScalarVectorStreamFunctions ( char);
DefineScalarVectorStreamFunctions (unsigned char);
DefineScalarVectorStreamFunctions ( short);
DefineScalarVectorStreamFunctions (unsigned short);
DefineScalarVectorStreamFunctions ( int);
DefineScalarVectorStreamFunctions (unsigned int);
DefineScalarVectorStreamFunctions ( long);
DefineScalarVectorStreamFunctions (unsigned long);
DefineScalarVectorStreamFunctions ( __int64);
DefineScalarVectorStreamFunctions (unsigned __int64);
DefineScalarVectorStreamFunctions (float);
DefineScalarVectorStreamFunctions (double);
DefineScalarVectorStreamFunctions (long double);