//------------------------------------------------------------------------------ // File: PStream.cpp // // Desc: DirectShow base classes. // // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ #include #include #ifdef PERF #include #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)