You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
585 lines
20 KiB
585 lines
20 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 1999-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
MPC_streams.h
|
|
|
|
Abstract:
|
|
This file includes and defines things for handling streams.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 07/10/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#if !defined(__INCLUDED___MPC___STREAMS_H___)
|
|
#define __INCLUDED___MPC___STREAMS_H___
|
|
|
|
#include <MPC_main.h>
|
|
#include <MPC_COM.h>
|
|
|
|
#include <set>
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace MPC
|
|
{
|
|
//
|
|
// Some forward declarations...
|
|
//
|
|
class CComHGLOBAL;
|
|
|
|
////////////////////
|
|
|
|
//
|
|
// Non-abstract class, meant to provide a do-nothing stub for real stream implementations.
|
|
//
|
|
class BaseStream : public IStream
|
|
{
|
|
public:
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ISequentialStream Interface
|
|
//
|
|
STDMETHOD(Read )( /*[out]*/ void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbRead );
|
|
STDMETHOD(Write)( /*[in] */ const void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbWritten );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IStream Interface
|
|
//
|
|
STDMETHOD(Seek )( /*[in]*/ LARGE_INTEGER libMove , /*[in]*/ DWORD dwOrigin, /*[out]*/ ULARGE_INTEGER *plibNewPosition );
|
|
STDMETHOD(SetSize)( /*[in]*/ ULARGE_INTEGER libNewSize );
|
|
|
|
STDMETHOD(CopyTo)( /*[in]*/ IStream* pstm, /*[in]*/ ULARGE_INTEGER cb, /*[out]*/ ULARGE_INTEGER *pcbRead, /*[out]*/ ULARGE_INTEGER *pcbWritten );
|
|
|
|
STDMETHOD(Commit)( /*[in]*/ DWORD grfCommitFlags );
|
|
STDMETHOD(Revert)( );
|
|
|
|
STDMETHOD(LockRegion )( /*[in]*/ ULARGE_INTEGER libOffset, /*[in]*/ ULARGE_INTEGER cb, /*[in]*/ DWORD dwLockType );
|
|
STDMETHOD(UnlockRegion)( /*[in]*/ ULARGE_INTEGER libOffset, /*[in]*/ ULARGE_INTEGER cb, /*[in]*/ DWORD dwLockType );
|
|
|
|
STDMETHOD(Stat)( /*[out]*/ STATSTG *pstatstg, /*[in]*/ DWORD grfStatFlag);
|
|
|
|
STDMETHOD(Clone)( /*[out]*/ IStream* *ppstm );
|
|
|
|
|
|
static HRESULT TransferData( /*[in]*/ IStream* src, /*[in]*/ IStream* dst, /*[in]*/ ULONG ulCount = -1, /*[out]*/ ULONG *ulDone = NULL );
|
|
};
|
|
|
|
|
|
//
|
|
// Class that wraps files around an IStream interface.
|
|
//
|
|
class ATL_NO_VTABLE FileStream : // Hungarian: hpcfs
|
|
public CComObjectRootEx<MPC::CComSafeMultiThreadModel>,
|
|
public BaseStream
|
|
{
|
|
MPC::wstring m_szFile;
|
|
DWORD m_dwDesiredAccess;
|
|
DWORD m_dwDisposition;
|
|
DWORD m_dwSharing;
|
|
HANDLE m_hfFile;
|
|
bool m_fDeleteOnRelease;
|
|
|
|
public:
|
|
|
|
BEGIN_COM_MAP(FileStream)
|
|
COM_INTERFACE_ENTRY(IStream)
|
|
COM_INTERFACE_ENTRY(ISequentialStream)
|
|
END_COM_MAP()
|
|
|
|
FileStream();
|
|
virtual ~FileStream();
|
|
|
|
HRESULT Close();
|
|
|
|
HRESULT Init ( /*[in]*/ LPCWSTR szFile, /*[in]*/ DWORD dwDesiredAccess, /*[in]*/ DWORD dwDisposition, /*[in]*/ DWORD dwSharing, /*[in]*/ HANDLE hfFile = NULL );
|
|
HRESULT InitForRead ( /*[in]*/ LPCWSTR szFile, /*[in]*/ HANDLE hfFile = NULL );
|
|
HRESULT InitForReadWrite( /*[in]*/ LPCWSTR szFile, /*[in]*/ HANDLE hfFile = NULL );
|
|
HRESULT InitForWrite ( /*[in]*/ LPCWSTR szFile, /*[in]*/ HANDLE hfFile = NULL );
|
|
|
|
HRESULT DeleteOnRelease( /*[in]*/ bool fFlag = true );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ISequentialStream Interface
|
|
//
|
|
STDMETHOD(Read )( /*[out]*/ void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbRead );
|
|
STDMETHOD(Write)( /*[in] */ const void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbWritten );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IStream Interface
|
|
//
|
|
STDMETHOD(Seek)( /*[in]*/ LARGE_INTEGER libMove, /*[in]*/ DWORD dwOrigin, /*[out]*/ ULARGE_INTEGER *plibNewPosition );
|
|
|
|
STDMETHOD(Stat)( /*[out]*/ STATSTG *pstatstg, /*[in]*/ DWORD grfStatFlag);
|
|
|
|
STDMETHOD(Clone)( /*[out]*/ IStream* *ppstm );
|
|
};
|
|
|
|
|
|
//
|
|
// Class that encrypts/decrypts data on-the-fly.
|
|
//
|
|
class ATL_NO_VTABLE EncryptedStream : // Hungarian: hpcefs
|
|
public CComObjectRootEx<MPC::CComSafeMultiThreadModel>,
|
|
public BaseStream
|
|
{
|
|
CComPtr<IStream> m_pStream;
|
|
HCRYPTPROV m_hCryptProv;
|
|
HCRYPTKEY m_hKey;
|
|
HCRYPTHASH m_hHash;
|
|
BYTE m_rgDecrypted[512];
|
|
DWORD m_dwDecryptedPos;
|
|
DWORD m_dwDecryptedLen;
|
|
|
|
public:
|
|
BEGIN_COM_MAP(EncryptedStream)
|
|
COM_INTERFACE_ENTRY(IStream)
|
|
COM_INTERFACE_ENTRY(ISequentialStream)
|
|
END_COM_MAP()
|
|
|
|
EncryptedStream();
|
|
virtual ~EncryptedStream();
|
|
|
|
|
|
HRESULT Close();
|
|
|
|
HRESULT Init( /*[in]*/ IStream* pStream, /*[in]*/ LPCWSTR szPassword );
|
|
HRESULT Init( /*[in]*/ IStream* pStream, /*[in]*/ HCRYPTKEY hKey );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ISequentialStream Interface
|
|
//
|
|
STDMETHOD(Read )( /*[out]*/ void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbRead );
|
|
STDMETHOD(Write)( /*[in] */ const void* pv, /*[in]*/ ULONG cb, /*[out]*/ ULONG *pcbWritten );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IStream Interface
|
|
//
|
|
STDMETHOD(Seek)( /*[in]*/ LARGE_INTEGER libMove, /*[in]*/ DWORD dwOrigin, /*[out]*/ ULARGE_INTEGER *plibNewPosition );
|
|
|
|
STDMETHOD(Stat)( /*[out]*/ STATSTG *pstatstg, /*[in]*/ DWORD grfStatFlag);
|
|
|
|
STDMETHOD(Clone)( /*[out]*/ IStream* *ppstm );
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class Serializer // Hungarian: stream
|
|
{
|
|
DWORD m_dwFlags;
|
|
|
|
public:
|
|
virtual ~Serializer() {};
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL ) = 0;
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen ) = 0;
|
|
|
|
virtual void put_Flags( /*[in]*/ DWORD dwFlags ) { m_dwFlags = dwFlags; }
|
|
virtual DWORD get_Flags( ) { return m_dwFlags; }
|
|
|
|
////////////////////////////////////////
|
|
|
|
//
|
|
// We cannot rely on the compiler finding the right method,
|
|
// since all these types map to VOID*, so the last one wins...
|
|
//
|
|
inline HRESULT HWND_read ( /*[out]*/ HWND& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT HWND_write( /*[in] */ const HWND& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Specialization of In/Out operators for various data types.
|
|
//
|
|
inline HRESULT operator>>( /*[out]*/ bool& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const bool& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ VARIANT_BOOL& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const VARIANT_BOOL& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ int& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const int& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ long& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const long& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ DWORD& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const DWORD& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ DATE& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const DATE& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ SYSTEMTIME& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const SYSTEMTIME& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
inline HRESULT operator>>( /*[out]*/ CLSID& val ) { return read ( &val, sizeof(val) ); }
|
|
inline HRESULT operator<<( /*[in] */ const CLSID& val ) { return write( &val, sizeof(val) ); }
|
|
|
|
HRESULT operator>>( /*[out]*/ MPC::string& val );
|
|
HRESULT operator<<( /*[in] */ const MPC::string& val );
|
|
|
|
HRESULT operator>>( /*[out]*/ MPC::wstring& val );
|
|
HRESULT operator<<( /*[in] */ const MPC::wstring& val );
|
|
|
|
HRESULT operator>>( /*[out]*/ CComBSTR& val );
|
|
HRESULT operator<<( /*[in] */ const CComBSTR& val );
|
|
|
|
HRESULT operator>>( /*[out]*/ CComHGLOBAL& val );
|
|
HRESULT operator<<( /*[in] */ const CComHGLOBAL& val );
|
|
|
|
HRESULT operator>>( /*[out]*/ CComPtr<IStream>& val );
|
|
HRESULT operator<<( /*[in] */ IStream* val );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_File : public Serializer
|
|
{
|
|
HANDLE m_hfFile;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
Serializer_File( /*[in]*/ HANDLE hfFile );
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_Text : public Serializer
|
|
{
|
|
MPC::Serializer& m_stream;
|
|
|
|
public:
|
|
Serializer_Text( /*[in]*/ Serializer& stream ) : m_stream( stream ) {}
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_Http : public Serializer
|
|
{
|
|
HINTERNET m_hReq;
|
|
|
|
public:
|
|
Serializer_Http( HINTERNET hReq );
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_Fake : public Serializer
|
|
{
|
|
DWORD m_dwSize;
|
|
|
|
public:
|
|
Serializer_Fake();
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Additional methods.
|
|
//
|
|
DWORD GetSize();
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_Memory : public Serializer
|
|
{
|
|
HANDLE m_hHeap;
|
|
|
|
BYTE* m_pData;
|
|
DWORD m_dwAllocated;
|
|
DWORD m_dwSize;
|
|
bool m_fFixed;
|
|
|
|
DWORD m_dwCursor_Write;
|
|
DWORD m_dwCursor_Read;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Alloc( /*[in]*/ DWORD dwSize );
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
Serializer_Memory( HANDLE hHeap=NULL );
|
|
virtual ~Serializer_Memory();
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Additional methods.
|
|
//
|
|
void Reset ();
|
|
void Rewind();
|
|
|
|
bool IsEOR();
|
|
bool IsEOW();
|
|
|
|
DWORD GetAvailableForRead ();
|
|
DWORD GetAvailableForWrite();
|
|
|
|
HRESULT SetSize( /*[in]*/ DWORD dwSize );
|
|
DWORD GetSize( );
|
|
BYTE* GetData( );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_IStream : public Serializer
|
|
{
|
|
CComPtr<IStream> m_stream;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
Serializer_IStream( /*[in]*/ IStream* stream = NULL );
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Additional methods.
|
|
//
|
|
HRESULT Reset ( );
|
|
HRESULT GetStream( /*[out]*/ IStream* *pVal );
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
|
|
class Serializer_Buffering : public Serializer
|
|
{
|
|
static const int MODE_READ = 1;
|
|
static const int MODE_WRITE = -1;
|
|
|
|
MPC::Serializer& m_stream;
|
|
BYTE m_rgTransitBuffer[1024];
|
|
DWORD m_dwAvailable;
|
|
DWORD m_dwPos;
|
|
int m_iMode;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
Serializer_Buffering( /*[in]*/ Serializer& stream );
|
|
virtual ~Serializer_Buffering();
|
|
|
|
virtual HRESULT read ( /*[in]*/ void* pBuf, /*[in]*/ DWORD dwLen, /*[out]*/ DWORD* dwRead = NULL );
|
|
virtual HRESULT write( /*[in]*/ const void* pBuf, /*[in]*/ DWORD dwLen );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Additional methods.
|
|
//
|
|
HRESULT Reset();
|
|
HRESULT Flush();
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Specialization for lists.
|
|
//
|
|
|
|
template <class _Ty, class _A> HRESULT operator>>( /*[in]*/ Serializer& stream, /*[out]*/ std::list<_Ty, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator>> std::list" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount;
|
|
|
|
|
|
val.clear();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> dwCount);
|
|
while(dwCount--)
|
|
{
|
|
_Ty value;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> value);
|
|
|
|
val.push_back( value );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
template <class _Ty, class _A> HRESULT operator<<( /*[in]*/ Serializer& stream, /*[in]*/ const std::list<_Ty, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator<< std::list" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount = val.size();
|
|
std::list<_Ty, _A>::iterator it = val.begin();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << dwCount);
|
|
while(dwCount--)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << (*it++));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Specialization for maps.
|
|
//
|
|
|
|
template <class _K, class _Ty, class _Pr, class _A> HRESULT operator>>( /*[in]*/ Serializer& stream, /*[out]*/ std::map<_K, _Ty, _Pr, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator>> std::map" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount;
|
|
|
|
|
|
val.clear();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> dwCount);
|
|
while(dwCount--)
|
|
{
|
|
_K key;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> key);
|
|
{
|
|
_Ty value;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> value);
|
|
|
|
val[key] = value;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
template <class _K, class _Ty, class _Pr, class _A> HRESULT operator<<( /*[in]*/ Serializer& stream, /*[out]*/ const std::map<_K, _Ty, _Pr, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator<< std::map" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount = val.size();
|
|
std::map<_K, _Ty, _Pr, _A>::iterator it = val.begin();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << dwCount);
|
|
while(dwCount--)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << it ->first );
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << (it++)->second);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Specialization for sets.
|
|
//
|
|
|
|
template <class _K, class _Pr, class _A> HRESULT operator>>( /*[in]*/ Serializer& stream, /*[out]*/ std::set<_K, _Pr, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator>> std::map" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount;
|
|
|
|
|
|
val.clear();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> dwCount);
|
|
while(dwCount--)
|
|
{
|
|
_K key;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> key);
|
|
|
|
val.insert( key );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
template <class _K, class _Pr, class _A> HRESULT operator<<( /*[in]*/ Serializer& stream, /*[out]*/ const std::set<_K, _Pr, _A>& val )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "operator<< std::map" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCount = val.size();
|
|
std::set<_K, _Pr, _A>::iterator it = val.begin();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << dwCount);
|
|
while(dwCount--)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << *it++);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
}; // namespace
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#endif // !defined(__INCLUDED___MPC___STREAMS_H___)
|