text: //------------------------------------------------------------------------------
  // File: PStream.cpp
  //
  // Desc: DirectShow base classes.
  //
  // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
  //------------------------------------------------------------------------------
  
  
  #include <streams.h>
  #include <strsafe.h>
  
  #ifdef PERF
  #include <measure.h>
  #endif
  // #include "pstream.h"  in streams.h
  
  //
  // Constructor
  //
  CPersistStream::CPersistStream(IUnknown *punk, __inout HRESULT *phr)
      : mPS_fDirty(FALSE)
  {
      mPS_dwFileVersion = GetSoftwareVersion();
  }
  
  
  //
  // Destructor
  //
  CPersistStream::~CPersistStream() {
      // Nothing to do
  }
  
  #if 0
  SAMPLE CODE TO COPY - not active at the moment
  
  //
  // NonDelegatingQueryInterface
  //
  // This object supports IPersist & IPersistStream
  STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
  {
      if (riid == IID_IPersist) {
          return GetInterface((IPersist *) this, ppv);      // ???
      }
      else if (riid == IID_IPersistStream) {
          return GetInterface((IPersistStream *) this, ppv);
      }
      else {
          return CUnknown::NonDelegatingQueryInterface(riid, ppv);
      }
  }
  #endif
  
  
  //
  // WriteToStream
  //
  // Writes to the stream (default action is to write nothing)
  HRESULT CPersistStream::WriteToStream(IStream *pStream)
  {
      // You can override this to do things like
      // hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL);
  
      return NOERROR;
  }
  
  
  
  HRESULT CPersistStream::ReadFromStream(IStream * pStream)
  {
      // You can override this to do things like
      // hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL);
  
      return NOERROR;
  }
  
  
  //
  // Load
  //
  // Load all the data from the given stream
  STDMETHODIMP CPersistStream::Load(LPSTREAM pStm)
  {
      HRESULT hr;
      // Load the version number then the data
      mPS_dwFileVersion = ReadInt(pStm, hr);
      if (FAILED(hr)) {
          return hr;
      }
  
      return ReadFromStream(pStm);
  }  // Load
  
  
  
  //
  // Save
  //
  // Save the contents of this Stream.
  STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty)
  {
  
      HRESULT hr = WriteInt(pStm, GetSoftwareVersion());
      if (FAILED(hr)) {
          return hr;
      }
  
      hr = WriteToStream(pStm);
      if (FAILED(hr)) {
          return hr;
      }
  
      mPS_fDirty = !fClearDirty;
  
      return hr;
  } // Save
  
  
  // WriteInt
  //
  // Writes an integer to an IStream as 11 UNICODE characters followed by one space.
  // You could use this for shorts or unsigneds or anything (up to 32 bits)
  // where the value isn't actually truncated by squeezing it into 32 bits.
  // Values such as (unsigned) 0x80000000 would come out as -2147483648
  // but would then load as 0x80000000 through ReadInt.  Cast as you please.
  
  STDAPI WriteInt(IStream *pIStream, int n)
  {
      WCHAR Buff[13];  // Allows for trailing null that we don't write
      (void)StringCchPrintfW(Buff, NUMELMS(Buff),L"%011d ",n);
      return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL);
  } // WriteInt
  
  
  // ReadInt
  //
  // Reads an integer from an IStream.
  // Read as 4 bytes.  You could use this for shorts or unsigneds or anything
  // where the value isn't actually truncated by squeezing it into 32 bits
  // Striped down subset of what sscanf can do (without dragging in the C runtime)
  
  STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr)
  {
  
      int Sign = 1;
      unsigned int n = 0;    // result wil be n*Sign
      WCHAR wch;
  
      hr = pIStream->Read( &wch, sizeof(wch), NULL);
      if (FAILED(hr)) {
          return 0;
      }
  
      if (wch==L'-'){
          Sign = -1;
          hr = pIStream->Read( &wch, sizeof(wch), NULL);
          if (FAILED(hr)) {
              return 0;
          }
      }
  
      for( ; ; ) {
          if (wch>=L'0' && wch<=L'9') {
              n = 10*n+(int)(wch-L'0');
          } else if (  wch == L' '
                    || wch == L'\t'
                    || wch == L'\r'
                    || wch == L'\n'
                    || wch == L'\0'
                    ) {
              break;
          } else {
              hr = VFW_E_INVALID_FILE_FORMAT;
              return 0;
          }
  
          hr = pIStream->Read( &wch, sizeof(wch), NULL);
          if (FAILED(hr)) {
              return 0;
          }
      }
  
      if (n==0x80000000 && Sign==-1) {
          // This is the negative number that has no positive version!
          return (int)n;
      }
      else return (int)n * Sign;
  } // ReadInt
  
  
  // The microsoft C/C++ compile generates level 4 warnings to the effect that
  // a particular inline function (from some base class) was not needed.
  // This line gets rid of hundreds of such unwanted messages and makes
  // -W4 compilation feasible:
  #pragma warning(disable: 4514)
  