198 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//------------------------------------------------------------------------------
 | 
						|
// 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)
 |