Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

342 lines
7.9 KiB

//-----------------------------------------------------------------------------
// SSBuf.h
//
// Copyright (C) 1995, Microsoft Corporation
//
// Purpose:
// Subclass Map, Set, and Array templates to handle versioning and
// reloading directly from a stream.
//
// Revision History:
//
// [] 13-Jan-1995 Dans Created
// [] 16-Apr-1995 Dans Added ArrayVer<> template
//
//-----------------------------------------------------------------------------
#if !defined(_ssbuf_h)
#define _ssbuf_h 1
// Depends on buffer.h
#include <stdlib.h>
#include <search.h>
#include <array.h>
#include <map.h>
#include <set.h>
#include <misc.h>
//
// All streams and sub-streams hav this header followed by the
// stream specific data
//
struct STRMHDR {
DWORD dwSig;
union {
DWORD cEntries;
DWORD cb;
};
long lVer;
DWORD dwReserved;
};
template <unsigned _cbExtra>
struct UserHdr {
unsigned __int32 cb;
BYTE rgb[ _cbExtra ];
};
//
// Versioned Maps
//
template <class D, class R, class H, unsigned _cbExtra>
class MapVer : public Map<D, R, H> {
private:
enum { sig = sigMagic };
typedef Map<D,R,H> BaseClass;
typedef UserHdr<_cbExtra> UsrHdr;
long m_lVer;
UsrHdr m_usrhdr;
public:
MapVer ( long lVer ) {
m_lVer = lVer;
m_usrhdr.cb = _cbExtra;
memset ( m_usrhdr.rgb, 0, _cbExtra );
}
// overload the relevant functions to handle the versioning
CB cbSave() const;
BOOL save ( Buffer * );
BOOL reload ( PB * );
// couple of supporting functions for user headers and direct
// to stream ops.
BOOL reloadStream ( Stream * );
BYTE * PbUserData();
};
template <class D, class R, class H, unsigned _cbExtra> inline
CB MapVer<D,R,H,_cbExtra>::cbSave() const {
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
}
template <class D, class R, class H, unsigned _cbExtra>
BOOL MapVer<D,R,H,_cbExtra>::save ( Buffer * pbuf ) {
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
assert ( m_usrhdr.cb == _cbExtra );
return
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
BaseClass::save ( pbuf );
}
template <class D, class R, class H, unsigned _cbExtra>
BOOL MapVer<D,R,H,_cbExtra>::reload ( PB * ppb ) {
STRMHDR hdr;
BOOL fRet = fFalse;
debug(PB pbT = *ppb;)
hdr = *(STRMHDR UNALIGNED *) *ppb;
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
*ppb += sizeof(hdr);
// reload the user data
unsigned __int32 cbUser;
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
*ppb += sizeof(unsigned __int32);
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
*ppb += _cbExtra;
// now do the actual map class
fRet = BaseClass::reload ( ppb );
assert ( pbT + hdr.cb == *ppb );
}
else {
// something bogus is going on, skip the header...
*ppb += max ( hdr.cb, sizeof(hdr) );
}
return fRet;
}
template <class D, class R, class H, unsigned _cbExtra>
BOOL MapVer<D,R,H,_cbExtra>::reloadStream ( Stream * pstream ) {
PB pb;
CB cb = pstream->QueryCb();
BOOL fRet = fFalse;
if ( cb > 0 ) {
Buffer buf;
if ( buf.Reserve ( cb, &pb ) ) {
if ( pstream->Read2 ( 0, pb, cb ) ) {
fRet = reload ( &pb );
}
}
}
else {
fRet = fTrue;
}
return fRet;
}
template <class D, class R, class H, unsigned _cbExtra> inline
BYTE * MapVer<D,R,H,_cbExtra>::PbUserData() {
//precondition ( _cbExtra );
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
}
//
// Versioned Sets
//
template <class D, class H, unsigned _cbExtra>
class SetVer : public Set<D,H> {
private:
enum { sig = sigMagic };
typedef Set<D,H> BaseClass;
typedef UserHdr<_cbExtra> UsrHdr;
long m_lVer;
UsrHdr m_usrhdr;
public:
SetVer ( long lVer ) {
m_lVer = lVer;
m_usrhdr.cb = _cbExtra;
}
// overload the relevant functions to handle the versioning
CB cbSave() const;
BOOL save ( Buffer * );
BOOL reload ( PB * );
// couple of supporting functions for user headers and direct
// to stream ops.
BOOL reloadStream ( Stream * );
BYTE * PbUserData();
};
template <class D, class H, unsigned _cbExtra> inline
CB SetVer<D,H,_cbExtra>::cbSave() const {
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
}
template <class D, class H, unsigned _cbExtra> inline
BOOL SetVer<D,H,_cbExtra>::save ( Buffer * pbuf ) {
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
assert ( m_usrhdr.cb == _cbExtra );
return
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
BaseClass::save ( pbuf );
}
template <class D, class H, unsigned _cbExtra>
BOOL SetVer<D,H,_cbExtra>::reload ( PB * ppb ) {
STRMHDR hdr;
BOOL fRet = fFalse;
debug(PB pbT = *ppb;)
hdr = *(STRMHDR UNALIGNED *) *ppb;
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
*ppb += sizeof(hdr);
// reload the user data
unsigned __int32 cbUser;
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
*ppb += sizeof(unsigned __int32);
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
*ppb += _cbExtra;
// now do the actual set class
fRet = BaseClass::reload ( ppb );
assert ( pbT + hdr.cb == *ppb );
}
else {
// something bogus is going on, skip the header...
*ppb += max(hdr.cb, sizeof(hdr));
}
return fRet;
}
template <class D, class H, unsigned _cbExtra>
BOOL SetVer<D,H,_cbExtra>::reloadStream ( Stream * pstream ) {
PB pb;
CB cb = pstream->QueryCb();
BOOL fRet = fFalse;
if ( cb > 0 ) {
Buffer buf;
if ( buf.Reserve ( cb, &pb ) ) {
if ( pstream->Read2 ( 0, pb, cb ) ) {
fRet = reload ( &pb );
}
}
}
else {
fRet = fTrue;
}
return fRet;
}
template <class D, class H, unsigned _cbExtra> inline
BYTE * SetVer<D,H,_cbExtra>::PbUserData() {
precondition ( _cbExtra );
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
}
//
// Versioned arrays
//
template <class T, unsigned _cbExtra>
class ArrayVer : public Array<T> {
private:
enum { sig = sigMagic };
typedef Array<T> BaseClass;
typedef UserHdr<_cbExtra> UsrHdr;
long m_lVer;
UsrHdr m_usrhdr;
public:
ArrayVer ( long lVer ) {
m_lVer = lVer;
m_usrhdr.cb = _cbExtra;
memset ( m_usrhdr.rgb, 0, _cbExtra );
}
// overload the relevant functions to handle the versioning
CB cbSave() const;
BOOL save ( Buffer * );
BOOL reload ( PB * );
// couple of supporting functions for user headers and direct
// to stream ops.
BOOL reloadStream ( Stream * );
BYTE * PbUserData();
};
template <class T, unsigned _cbExtra> inline
CB ArrayVer<T,_cbExtra>::cbSave() const {
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
}
template <class T, unsigned _cbExtra>
BOOL ArrayVer<T,_cbExtra>::save ( Buffer * pbuf ) {
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
assert ( m_usrhdr.cb == _cbExtra );
return
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
BaseClass::save ( pbuf );
}
template <class T, unsigned _cbExtra>
BOOL ArrayVer<T,_cbExtra>::reload ( PB * ppb ) {
STRMHDR hdr;
BOOL fRet = fFalse;
debug(PB pbT = *ppb;)
hdr = *(STRMHDR UNALIGNED *) *ppb;
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
*ppb += sizeof(hdr);
// reload the user data
unsigned __int32 cbUser;
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
*ppb += sizeof(unsigned __int32);
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
*ppb += _cbExtra;
// now do the actual array
fRet = BaseClass::reload ( ppb );
assert ( pbT + hdr.cb == *ppb );
}
else {
// something bogus is going on, skip the header...
*ppb += max ( hdr.cb, sizeof(hdr) );
}
return fRet;
}
template <class T, unsigned _cbExtra>
BOOL ArrayVer<T,_cbExtra>::reloadStream ( Stream * pstream ) {
PB pb;
CB cb = pstream->QueryCb();
BOOL fRet = fFalse;
if ( cb > 0 ) {
Buffer buf;
if ( buf.Reserve ( cb, &pb ) ) {
if ( pstream->Read2 ( 0, pb, cb ) ) {
fRet = reload ( &pb );
}
}
}
else {
fRet = fTrue;
}
return fRet;
}
template <class T, unsigned _cbExtra>
BYTE * ArrayVer<T,_cbExtra>::PbUserData() {
//precondition ( _cbExtra );
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
}
#endif