2009-02-09 21:15:56 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// File: PStream.cpp
|
|
|
|
//
|
|
|
|
// Desc: DirectShow base classes.
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#include "streams.h"
|
|
|
|
|
|
|
|
#ifdef PERF
|
|
|
|
#include <measure.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Constructor
|
|
|
|
//
|
|
|
|
CPersistStream::CPersistStream(IUnknown *punk, 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, 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, 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)
|