Changelog: - first part of a new IAVIEditStream implementation. - Fixed/Added some parameter checking. - Fixed bug in EditStreamSetInfoW. - Fixed bug in avifil32.spec (str instead of wstr). - Fixed cosmetic bug in IAVIStreamImpl_fnRelease. - Fixed typo. Michael
Index: dlls/avifil32/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/avifil32/Makefile.in,v retrieving revision 1.27 diff -d -u -r1.27 Makefile.in --- dlls/avifil32/Makefile.in 23 Aug 2003 22:54:53 -0000 1.27 +++ dlls/avifil32/Makefile.in 19 Sep 2003 15:52:32 -0000 @@ -16,6 +16,7 @@ acmstream.c \ api.c \ avifile.c \ + editstream.c \ extrachunk.c \ factory.c \ getframe.c \ Index: dlls/avifil32/api.c =================================================================== RCS file: /home/wine/wine/dlls/avifil32/api.c,v retrieving revision 1.23 diff -d -u -r1.23 api.c --- dlls/avifil32/api.c 5 Sep 2003 23:08:44 -0000 1.23 +++ dlls/avifil32/api.c 19 Sep 2003 15:52:40 -0000 @@ -395,6 +395,9 @@ { TRACE("(%p,%p,%p)\n", pfile, avis, asi); + if (pfile == NULL) + return AVIERR_BADHANDLE; + return IAVIFile_CreateStream(pfile, avis, asi); } @@ -2030,7 +2033,7 @@ IAVIEditStream *pEdit = NULL; HRESULT hr; - FIXME("(%p,%p), semi stub!\n", ppEditable, pSource); + TRACE("(%p,%p)\n", ppEditable, pSource); if (ppEditable == NULL) return AVIERR_BADPARAM; @@ -2040,14 +2043,21 @@ if (pSource != NULL) { hr = IAVIStream_QueryInterface(pSource, &IID_IAVIEditStream, (LPVOID*)&pEdit); - if (FAILED(hr) || pEdit == NULL) { - /* need own implementation of IAVIEditStream */ + if (SUCCEEDED(hr) && pEdit != NULL) { + hr = IAVIEditStream_Clone(pEdit, ppEditable); + IAVIEditStream_Release(pEdit); - return AVIERR_UNSUPPORTED; + return hr; } } - hr = IAVIEditStream_Clone(pEdit, ppEditable); + /* need own implementation of IAVIEditStream */ + pEdit = AVIFILE_CreateEditStream(pSource); + if (pEdit == NULL) + return AVIERR_MEMORY; + + hr = IAVIEditStream_QueryInterface(pEdit, &IID_IAVIStream, + (LPVOID*)ppEditable); IAVIEditStream_Release(pEdit); return hr; @@ -2121,13 +2131,13 @@ TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult); + if (ppResult != NULL) + *ppResult = NULL; if (pStream == NULL) return AVIERR_BADHANDLE; - if (plStart == NULL || plLength == NULL || ppResult == NULL) + if (plStart == NULL || plLength == NULL) return AVIERR_BADPARAM; - *ppResult = NULL; - hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit); if (SUCCEEDED(hr) && pEdit != NULL) { hr = IAVIEditStream_Cut(pEdit, plStart, plLength, ppResult); @@ -2182,7 +2192,7 @@ if ((DWORD)size < sizeof(AVISTREAMINFOA)) return AVIERR_BADSIZE; - memcpy(&asiw, asi, sizeof(asi) - sizeof(asi->szName)); + memcpy(&asiw, asi, sizeof(asiw) - sizeof(asiw.szName)); MultiByteToWideChar(CP_ACP, 0, asi->szName, -1, asiw.szName, sizeof(asiw.szName)); Index: dlls/avifil32/avifil32.spec =================================================================== RCS file: /home/wine/wine/dlls/avifil32/avifil32.spec,v retrieving revision 1.20 diff -d -u -r1.20 avifil32.spec --- dlls/avifil32/avifil32.spec 23 Aug 2003 22:54:53 -0000 1.20 +++ dlls/avifil32/avifil32.spec 19 Sep 2003 15:52:41 -0000 @@ -15,7 +15,7 @@ @ stdcall AVIFileInit() @ stub AVIFileOpen @ stdcall AVIFileOpenA(ptr str long ptr) -@ stdcall AVIFileOpenW(ptr str long ptr) +@ stdcall AVIFileOpenW(ptr wstr long ptr) @ stdcall AVIFileReadData(ptr long ptr ptr) @ stdcall AVIFileRelease(ptr) @ stdcall AVIFileWriteData(ptr long ptr long) Index: dlls/avifil32/avifile.c =================================================================== RCS file: /home/wine/wine/dlls/avifil32/avifile.c,v retrieving revision 1.38 diff -d -u -r1.38 avifile.c --- dlls/avifil32/avifile.c 5 Sep 2003 23:08:44 -0000 1.38 +++ dlls/avifil32/avifile.c 19 Sep 2003 15:52:51 -0000 @@ -305,8 +305,8 @@ for (i = 0; i < This->fInfo.dwStreams; i++) { if (This->ppStreams[i] != NULL) { if (This->ppStreams[i]->ref != 0) { - ERR(": someone has still a reference to stream %u (%p)!\n", - i, This->ppStreams[i]); + ERR(": someone has still %lu reference to stream %u (%p)!\n", + This->ppStreams[i]->ref, i, This->ppStreams[i]); } AVIFILE_DestructAVIStream(This->ppStreams[i]); LocalFree((HLOCAL)This->ppStreams[i]); @@ -529,7 +529,7 @@ if (lParam < 0) return AVIERR_BADPARAM; - /* Habe user write permissions? */ + /* Have user write permissions? */ if ((This->uMode & MMIO_RWMODE) == 0) return AVIERR_READONLY; @@ -756,10 +756,12 @@ return 0; } + This->ref--; + if (This->paf != NULL) IAVIFile_Release((PAVIFILE)This->paf); - return --This->ref; + return This->ref; } static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream *iface, LPARAM lParam1, Index: dlls/avifil32/avifile_private.h =================================================================== RCS file: /home/wine/wine/dlls/avifil32/avifile_private.h,v retrieving revision 1.8 diff -d -u -r1.8 avifile_private.h --- dlls/avifil32/avifile_private.h 23 Jun 2003 18:10:06 -0000 1.8 +++ dlls/avifil32/avifile_private.h 19 Sep 2003 15:52:52 -0000 @@ -57,6 +57,7 @@ DEFINE_AVIGUID(CLSID_ICMStream, 0x00020001, 0, 0); DEFINE_AVIGUID(CLSID_WAVFile, 0x00020003, 0, 0); DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0); +DEFINE_AVIGUID(IID_IEditStreamInternal, 0x0002000A,0,0); extern HMODULE AVIFILE_hModule; @@ -64,6 +65,7 @@ extern HRESULT AVIFILE_CreateWAVFile(REFIID riid, LPVOID *ppobj); extern HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppobj); extern HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppobj); +extern PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream); extern PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pstream); extern PAVIFILE AVIFILE_CreateAVITempFile(int nStreams,PAVISTREAM *ppStreams); Index: dlls/avifil32/getframe.c =================================================================== RCS file: /home/wine/wine/dlls/avifil32/getframe.c,v retrieving revision 1.9 diff -d -u -r1.9 getframe.c --- dlls/avifil32/getframe.c 9 Sep 2003 19:39:32 -0000 1.9 +++ dlls/avifil32/getframe.c 19 Sep 2003 15:52:54 -0000 @@ -171,7 +171,7 @@ if (!--(This->ref)) { AVIFILE_CloseCompressor(This); if (This->pStream != NULL) { - AVIStreamRelease(This->pStream); + IAVIStream_Release(This->pStream); This->pStream = NULL; } @@ -191,6 +191,10 @@ TRACE("(%p,%ld)\n", iface, lPos); + /* We don't want negative start values! -- marks invalid buffer content */ + if (lPos < 0) + return NULL; + /* check state */ if (This->pStream == NULL) return NULL; @@ -226,17 +230,18 @@ } if (lPos != This->lCurrentFrame) { - LONG lNext = AVIStreamFindSample(This->pStream, lPos, FIND_KEY|FIND_PREV); + LONG lNext = IAVIStream_FindSample(This->pStream,lPos,FIND_KEY|FIND_PREV); if (lNext == -1) - return NULL; + return NULL; /* frame doesn't exist */ if (lNext <= This->lCurrentFrame && This->lCurrentFrame < lPos) lNext = This->lCurrentFrame + 1; for (; lNext <= lPos; lNext++) { /* new format for this frame? */ if (This->bFormatChanges) { - AVIStreamReadFormat(This->pStream, lNext, This->lpInFormat, &This->cbInFormat); + IAVIStream_ReadFormat(This->pStream, lNext, + This->lpInFormat, &This->cbInFormat); if (This->lpOutFormat != NULL) { if (This->lpOutFormat->biBitCount <= 8) ICDecompressGetPalette(This->hic, This->lpInFormat, @@ -250,17 +255,26 @@ /* not enough memory for input buffer? */ readBytes = 0; if (FAILED(AVIStreamSampleSize(This->pStream, lNext, &readBytes))) + return NULL; /* bad thing, but bad things will happen */ + if (readBytes <= 0) { + ERR(": IAVIStream::REad doesn't return needed bytes!\n"); return NULL; + } + + /* IAVIStream::Read failed because of other reasons not buffersize? */ if (This->cbInBuffer >= readBytes) break; - This->lpInFormat = GlobalReAllocPtr(This->lpInFormat, This->cbInFormat + readBytes, 0); + This->cbInBuffer = This->cbInFormat + readBytes; + This->lpInFormat = GlobalReAllocPtr(This->lpInFormat, This->cbInBuffer, 0); if (This->lpInFormat == NULL) - return NULL; + return NULL; /* out of memory */ This->lpInBuffer = (BYTE*)This->lpInFormat + This->cbInFormat; } - if (readSamples != 1) + if (readSamples != 1) { + ERR(": no frames read\n"); return NULL; + } if (readBytes != 0) { This->lpInFormat->biSizeImage = readBytes; @@ -349,7 +363,8 @@ if (This->cbInBuffer == 0) This->cbInBuffer = 1024; - AVIStreamFormatSize(This->pStream, sInfo.dwStart, &This->cbInFormat); + IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, + NULL, &This->cbInFormat); This->lpInFormat = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, This->cbInFormat + This->cbInBuffer); @@ -358,8 +373,9 @@ return AVIERR_MEMORY; } - hr = AVIStreamReadFormat(This->pStream, sInfo.dwStart, This->lpInFormat, &This->cbInFormat); + hr = IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, + This->lpInFormat, &This->cbInFormat); if (FAILED(hr)) { AVIFILE_CloseCompressor(This); return hr; --- /dev/null 2002-09-09 22:24:09.000000000 +0200 +++ dlls/avifil32/editstream.c 2003-09-19 09:58:45.000000000 +0200 @@ -0,0 +1,1037 @@ +/* + * Copyright 2003 Michael Günnewig + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COM_NO_WINDOWS_H +#include <assert.h> +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "winerror.h" +#include "windowsx.h" +#include "mmsystem.h" +#include "vfw.h" + +#include "avifile_private.h" +#include "extrachunk.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(avifile); + +/***********************************************************************/ + +/* internal interface to get access to table of stream in an editable stream */ +typedef struct IEditStreamInternal IEditStreamInternal; + +typedef struct _EditStreamTable { + PAVISTREAM pStream; /* stream which contains the data */ + DWORD dwStart; /* where starts the part which is also our */ + DWORD dwLength; /* how many is also in this stream */ +} EditStreamTable; + +#define INTERFACE IEditStreamInternal +#define IEditStreamInternal_METHODS \ + IUnknown_METHODS \ + STDMETHOD(GetEditStreamImpl)(THIS_ LPVOID*) PURE; +ICOM_DEFINE(IEditStreamInternal, IUnknown) +#undef INTERFACE + +#define EditStreamEnd(This,streamNr) ((This)->pStreams[streamNr].dwStart + \ + (This)->pStreams[streamNr].dwLength) + +/***********************************************************************/ + +static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj); +static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface); +static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface); +static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM*ppResult); +static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM*ppResult); +static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM pSource, + LONG lStart,LONG lEnd); +static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface, + PAVISTREAM*ppResult); +static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface, + LPAVISTREAMINFOW asi,LONG size); + +struct ICOM_VTABLE(IAVIEditStream) ieditstream = { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IAVIEditStream_fnQueryInterface, + IAVIEditStream_fnAddRef, + IAVIEditStream_fnRelease, + IAVIEditStream_fnCut, + IAVIEditStream_fnCopy, + IAVIEditStream_fnPaste, + IAVIEditStream_fnClone, + IAVIEditStream_fnSetInfo +}; + +static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID*obj); +static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface); +static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface); +static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2); +static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size); +static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos, + LONG flags); +static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG*formatsize); +static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize); +static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start, + LONG samples,LPVOID buffer, + LONG buffersize,LONG*bytesread, + LONG*samplesread); +static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start, + LONG samples,LPVOID buffer, + LONG buffersize,DWORD flags, + LONG*sampwritten,LONG*byteswritten); +static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples); +static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc, + LPVOID lp,LONG *lpread); +static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc, + LPVOID lp,LONG size); +static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen); + +struct ICOM_VTABLE(IAVIStream) ieditstast = { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IEditAVIStream_fnQueryInterface, + IEditAVIStream_fnAddRef, + IEditAVIStream_fnRelease, + IEditAVIStream_fnCreate, + IEditAVIStream_fnInfo, + IEditAVIStream_fnFindSample, + IEditAVIStream_fnReadFormat, + IEditAVIStream_fnSetFormat, + IEditAVIStream_fnRead, + IEditAVIStream_fnWrite, + IEditAVIStream_fnDelete, + IEditAVIStream_fnReadData, + IEditAVIStream_fnWriteData, + IEditAVIStream_fnSetInfo +}; + +static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj); +static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface); +static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface); +static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl); + +struct ICOM_VTABLE(IEditStreamInternal) ieditstreaminternal = { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IEditStreamInternal_fnQueryInterface, + IEditStreamInternal_fnAddRef, + IEditStreamInternal_fnRelease, + IEditStreamInternal_fnGetEditStreamImpl +}; + +typedef struct _IAVIEditStreamImpl IAVIEditStreamImpl; + +typedef struct _IEditAVIStreamImpl { + /* IUnknown stuff */ + ICOM_VFIELD(IAVIStream); + + /* IAVIStream stuff */ + IAVIEditStreamImpl *pae; +} IEditAVIStreamImpl; + +typedef struct _IEditStreamInternalImpl { + /* IUnknown stuff */ + ICOM_VFIELD(IEditStreamInternal); + + /* IEditStreamInternal stuff */ + IAVIEditStreamImpl *pae; +} IEditStreamInternalImpl; + +struct _IAVIEditStreamImpl { + /* IUnknown stuff */ + ICOM_VFIELD(IAVIEditStream); + DWORD ref; + + /* IAVIEditStream stuff */ + IEditAVIStreamImpl iAVIStream; + IEditStreamInternalImpl iEditStreamInternal; + + AVISTREAMINFOW sInfo; + + EditStreamTable *pStreams; + DWORD nStreams; /* current fill level of pStreams table */ + DWORD nTableSize; /* size of pStreams table */ + + BOOL bDecompress; + PAVISTREAM pCurStream; + PGETFRAME pg; /* IGetFrame for pCurStream */ + LPBITMAPINFOHEADER lpFrame; /* frame of pCurStream */ +}; + +/***********************************************************************/ + +PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream) +{ + IAVIEditStreamImpl *pedit = NULL; + + pedit = (IAVIEditStreamImpl*)LocalAlloc(LPTR,sizeof(IAVIEditStreamImpl)); + if (pedit == NULL) + return NULL; + + pedit->lpVtbl = &ieditstream; + pedit->iAVIStream.lpVtbl = &ieditstast; + pedit->iAVIStream.pae = pedit; + pedit->iEditStreamInternal.lpVtbl = &ieditstreaminternal; + pedit->iEditStreamInternal.pae = pedit; + pedit->ref = 1; + + IAVIStream_Create((PAVISTREAM)&pedit->iAVIStream,(LPARAM)pstream,0); + + return (PAVIEDITSTREAM)pedit; +} + +static HRESULT AVIFILE_FindStreamInTable(IAVIEditStreamImpl* const This, + DWORD pos,PAVISTREAM *ppStream, + DWORD* streamPos, + DWORD* streamNr,BOOL bFindSample) +{ + DWORD n; + + TRACE("(%p,%lu,%p,%p,%p,%d)",This,pos,ppStream,streamPos, + streamNr,bFindSample); + + if (pos < This->sInfo.dwStart) + return AVIERR_BADPARAM; + + pos -= This->sInfo.dwStart; + for (n = 0; n < This->nStreams; n++) { + if (pos < This->pStreams[n].dwLength) { + *ppStream = This->pStreams[n].pStream; + *streamPos = This->pStreams[n].dwStart + pos; + if (streamNr != NULL) + *streamNr = n; + + return AVIERR_OK; + } + pos -= This->pStreams[n].dwLength; + } + if (pos == 0 && bFindSample) { + *ppStream = This->pStreams[--n].pStream; + *streamPos = EditStreamEnd(This, n); + if (streamNr != NULL) + *streamNr = n; + + TRACE(" -- pos=0 && b=1 -> (%p,%lu,%lu)\n",*ppStream, *streamPos, n); + return AVIERR_OK; + } else { + *ppStream = NULL; + *streamPos = 0; + if (streamNr != NULL) + *streamNr = 0; + + TRACE(" -> ERROR (NULL,0,0)\n"); + return AVIERR_BADPARAM; + } +} + +static LPVOID AVIFILE_ReadFrame(IAVIEditStreamImpl* const This, + PAVISTREAM pstream, LONG pos) +{ + PGETFRAME pg; + + TRACE("(%p,%p,%ld)\n",This,pstream,pos); + + if (pstream == NULL) + return NULL; + + /* if stream changes make sure that only palette changes */ + if (This->pCurStream != pstream) { + pg = AVIStreamGetFrameOpen(pstream, NULL); + if (pg == NULL) + return NULL; + if (This->pg != NULL) { + if (IGetFrame_SetFormat(pg, This->lpFrame, NULL, 0, 0, -1, -1)) { + AVIStreamGetFrameClose(pg); + ERR(": IGetFrame_SetFormat failed\n"); + return NULL; + } + AVIStreamGetFrameClose(This->pg); + } + This->pg = pg; + This->pCurStream = pstream; + } + + /* now get the decompressed frame */ + This->lpFrame = AVIStreamGetFrame(This->pg, pos); + if (This->lpFrame != NULL) + This->sInfo.dwSuggestedBufferSize = This->lpFrame->biSizeImage; + + return This->lpFrame; +} + +static HRESULT AVIFILE_RemoveStream(IAVIEditStreamImpl* const This, DWORD nr) +{ + assert(This != NULL); + assert(nr < This->nStreams); + + /* remove part nr */ + IAVIStream_Release(This->pStreams[nr].pStream); + This->nStreams--; + if (This->nStreams - nr > 0) { + memmove(This->pStreams + nr, This->pStreams + nr + 1, + (This->nStreams - nr) * sizeof(EditStreamTable)); + } + This->pStreams[This->nStreams].pStream = NULL; + This->pStreams[This->nStreams].dwStart = 0; + This->pStreams[This->nStreams].dwLength = 0; + + /* try to merge the part before the deleted one and the one after it */ + if (0 < nr && 0 < This->nStreams && + This->pStreams[nr - 1].pStream == This->pStreams[nr].pStream) { + if (EditStreamEnd(This, nr - 1) == This->pStreams[nr].dwStart) { + This->pStreams[nr - 1].dwLength += This->pStreams[nr].dwLength; + return AVIFILE_RemoveStream(This, nr); + } + } + + return AVIERR_OK; +} + +static BOOL AVIFILE_FormatsEqual(PAVISTREAM avi1, PAVISTREAM avi2) +{ + LPVOID fmt1 = NULL, fmt2 = NULL; + LONG size1, size2, start1, start2; + BOOL status = FALSE; + + assert(avi1 != NULL && avi2 != NULL); + + /* get stream starts and check format sizes */ + start1 = AVIStreamStart(avi1); + start2 = AVIStreamStart(avi2); + if (FAILED(AVIStreamFormatSize(avi1, start1, &size1))) + return FALSE; + if (FAILED(AVIStreamFormatSize(avi2, start2, &size2))) + return FALSE; + if (size1 != size2) + return FALSE; + + /* sizes match, now get formats and compare them */ + fmt1 = GlobalAllocPtr(GHND, size1); + if (fmt1 == NULL) + return FALSE; + if (SUCCEEDED(AVIStreamReadFormat(avi1, start1, fmt1, &size1))) { + fmt2 = GlobalAllocPtr(GHND, size1); + if (fmt2 != NULL) { + if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1))) + status = memcmp(fmt1, fmt2, size1); + } + } + + if (fmt2 != NULL) + GlobalFreePtr(fmt2); + GlobalFreePtr(fmt1); + + return status; +} + +/***********************************************************************/ + +static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + + TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj); + + if (IsEqualGUID(&IID_IUnknown, refiid) || + IsEqualGUID(&IID_IAVIEditStream, refiid)) { + *obj = iface; + IAVIEditStream_AddRef(iface); + + return S_OK; + } else if (IsEqualGUID(&IID_IAVIStream, refiid)) { + *obj = &This->iAVIStream; + IAVIEditStream_AddRef(iface); + + return S_OK; + } else if (IsEqualGUID(&IID_IEditStreamInternal, refiid)) { + *obj = &This->iEditStreamInternal; + IAVIEditStream_AddRef(iface); + + return S_OK; + } + + return OLE_E_ENUM_NOMORE; +} + +static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + + TRACE("(%p) -> %ld\n", iface, This->ref + 1); + return ++(This->ref); +} + +static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + DWORD i; + + TRACE("(%p) -> %ld\n", iface, This->ref - 1); + + if (!--(This->ref)) { + /* releaase memory */ + if (This->pg != NULL) + AVIStreamGetFrameClose(This->pg); + if (This->pStreams != NULL) { + for (i = 0; i < This->nStreams; i++) { + if (This->pStreams[i].pStream != NULL) + IAVIStream_Release(This->pStreams[i].pStream); + } + GlobalFreePtr(This->pStreams); + } + + LocalFree((HLOCAL)This); + return 0; + } + return This->ref; +} + +static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM*ppResult) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + PAVISTREAM stream; + DWORD start, len, streamPos, streamNr; + HRESULT hr; + + TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult); + + if (ppResult != NULL) + *ppResult = NULL; + if (plStart == NULL || plLength == NULL || *plStart < 0) + return AVIERR_BADPARAM; + + /* if asked for cutted part copy it before deleting */ + if (ppResult != NULL) { + hr = IAVIEditStream_Copy(iface, plStart, plLength, ppResult); + if (FAILED(hr)) + return hr; + } + + start = *plStart; + len = *plLength; + + /* now delete the requested part */ + while (len > 0) { + hr = AVIFILE_FindStreamInTable(This, start, &stream, + &streamPos, &streamNr, FALSE); + if (FAILED(hr)) + return hr; + if (This->pStreams[streamNr].dwStart == streamPos) { + /* deleting from start of part */ + if (len < This->pStreams[streamNr].dwLength) { + start += len; + This->pStreams[streamNr].dwStart += len; + This->pStreams[streamNr].dwLength -= len; + This->sInfo.dwLength -= len; + len = 0; + + /* we must return decompressed data now */ + This->bDecompress = TRUE; + } else { + /* deleting hole part */ + len -= This->pStreams[streamNr].dwLength; + AVIFILE_RemoveStream(This,streamNr); + } + } else if (EditStreamEnd(This, streamNr) <= streamPos + len) { + /* deleting at end of a part */ + DWORD count = EditStreamEnd(This, streamNr) - streamPos; + This->sInfo.dwLength -= count; + len -= count; + This->pStreams[streamNr].dwLength = + streamPos - This->pStreams[streamNr].dwStart; + } else { + /* splitting */ + if (This->nStreams + 1 >= This->nTableSize) { + This->pStreams = + GlobalReAllocPtr(This->pStreams, (This->nTableSize + 32) * sizeof(EditStreamTable), GMEM_SHARE|GHND); + if (This->pStreams == NULL) + return AVIERR_MEMORY; + This->nTableSize += 32; + } + memmove(This->pStreams + streamNr + 1, This->pStreams + streamNr, + (This->nStreams - streamNr) * sizeof(EditStreamTable)); + This->nStreams++; + + IAVIStream_AddRef(This->pStreams[streamNr + 1].pStream); + This->pStreams[streamNr + 1].dwStart = streamPos + len; + This->pStreams[streamNr + 1].dwLength = + EditStreamEnd(This, streamNr) - This->pStreams[streamNr + 1].dwStart; + + This->pStreams[streamNr].dwLength = + streamPos - This->pStreams[streamNr].dwStart; + This->sInfo.dwLength -= len; + len = 0; + } + } + + This->sInfo.dwEditCount++; + + return AVIERR_OK; +} + +static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM*ppResult) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + IAVIEditStreamImpl* pEdit; + HRESULT hr; + LONG start = 0; + + TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult); + + if (ppResult == NULL) + return AVIERR_BADPARAM; + *ppResult = NULL; + if (plStart == NULL || plLength == NULL || *plStart < 0 || *plLength < 0) + return AVIERR_BADPARAM; + + /* check bounds */ + if (*(LPDWORD)plLength > This->sInfo.dwLength) + *(LPDWORD)plLength = This->sInfo.dwLength; + if (*(LPDWORD)plStart < This->sInfo.dwStart) { + *(LPDWORD)plLength -= This->sInfo.dwStart - *(LPDWORD)plStart; + *(LPDWORD)plStart = This->sInfo.dwStart; + if (*plLength < 0) + return AVIERR_BADPARAM; + } + if (*(LPDWORD)plStart + *(LPDWORD)plLength > This->sInfo.dwStart + This->sInfo.dwLength) + *(LPDWORD)plLength = This->sInfo.dwStart + This->sInfo.dwLength - + *(LPDWORD)plStart; + + pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL); + if (pEdit == NULL) + return AVIERR_MEMORY; + + hr = IAVIEditStream_Paste((PAVIEDITSTREAM)pEdit,&start,plLength, + (PAVISTREAM)&This->iAVIStream,*plStart, + *plStart + *plLength); + *plStart = start; + if (FAILED(hr)) + IAVIEditStream_Release((PAVIEDITSTREAM)pEdit); + else + *ppResult = (PAVISTREAM)&pEdit->iAVIStream; + + return hr; +} + +static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart, + LONG*plLength,PAVISTREAM pSource, + LONG lStart,LONG lLength) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + AVISTREAMINFOW srcInfo; + IEditStreamInternal*pTable = NULL; + IAVIEditStreamImpl *pEdit = NULL; + + FIXME("(%p,%p,%p,%p,%ld,%ld),stub!\n",iface,plStart,plLength, + pSource,lStart,lLength); + + if (plStart == NULL || pSource == NULL || lLength < 0) + return AVIERR_BADPARAM; + if (This->sInfo.dwStart + This->sInfo.dwLength < *plStart) + return AVIERR_BADPARAM; /* FIXME: or change plStart to end of stream? */ + if (FAILED(IAVIStream_Info(pSource, &srcInfo, sizeof(srcInfo)))) + return AVIERR_ERROR; + if (lStart < srcInfo.dwStart || lStart >= srcInfo.dwStart + srcInfo.dwLength) + return AVIERR_BADPARAM; + if (This->sInfo.fccType != srcInfo.fccType) + return AVIERR_UNSUPPORTED; /* different stream types */ + if (This->sInfo.fccType == 0) { + IAVIStream_Info(pSource, &This->sInfo, sizeof(This->sInfo)); + This->sInfo.dwStart = *plStart; + This->sInfo.dwLength = 0; + } + if (lStart + lLength > srcInfo.dwStart + srcInfo.dwLength) + lLength = srcInfo.dwStart + srcInfo.dwLength - lStart; + if (lLength + *plStart >= 0x80000000) + return AVIERR_MEMORY; + + /* streamtype specific tests */ + if (srcInfo.fccType == streamtypeVIDEO) { + DWORD size; + + size = srcInfo.rcFrame.right - srcInfo.rcFrame.left; + if (size != This->sInfo.rcFrame.right - This->sInfo.rcFrame.left) + return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */ + size = srcInfo.rcFrame.bottom - srcInfo.rcFrame.top; + if (size != This->sInfo.rcFrame.bottom - This->sInfo.rcFrame.top) + return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */ + } else if (srcInfo.fccType == streamtypeAUDIO) { + if (! AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource)) + return AVIERR_UNSUPPORTED; + } else { + /* FIXME: streamtypeMIDI and streamtypeTEXT */ + return AVIERR_UNSUPPORTED; + } + + /* try to get an IEditStreamInternal interface */ + if (SUCCEEDED(IAVIStream_QueryInterface(pSource, &IID_IEditStreamInternal, + (LPVOID*)&pTable))) { + pTable->lpVtbl->GetEditStreamImpl(pTable, (LPVOID*)&pEdit); + pTable->lpVtbl->Release(pTable); + } + + /* FIXME: for video must check for change of format */ + /* FIXME: if stream to insert is an editable stream insert the + * 'sub-streams' else the given stream. + */ + + return AVIERR_UNSUPPORTED; +} + +static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface, + PAVISTREAM*ppResult) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + IAVIEditStreamImpl* pEdit; + DWORD i; + + TRACE("(%p,%p)\n",iface,ppResult); + + if (ppResult == NULL) + return AVIERR_BADPARAM; + *ppResult = NULL; + + pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL); + if (pEdit == NULL) + return AVIERR_MEMORY; + if (This->nStreams > pEdit->nTableSize) { + pEdit->pStreams = GlobalReAllocPtr(pEdit->pStreams, This->nStreams * sizeof(EditStreamTable),GMEM_SHARE|GHND); + if (pEdit->pStreams == NULL) + return AVIERR_MEMORY; + pEdit->nTableSize = This->nStreams; + } + pEdit->nStreams = This->nStreams; + memcpy(pEdit->pStreams, This->pStreams, + This->nStreams * sizeof(EditStreamTable)); + memcpy(&pEdit->sInfo,&This->sInfo,sizeof(This->sInfo)); + for (i = 0; i < This->nStreams; i++) { + if (pEdit->pStreams[i].pStream != NULL) + IAVIStream_AddRef(pEdit->pStreams[i].pStream); + } + + *ppResult = (PAVISTREAM)&pEdit->iAVIStream; + + return AVIERR_OK; +} + +static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface, + LPAVISTREAMINFOW asi,LONG size) +{ + ICOM_THIS(IAVIEditStreamImpl,iface); + + TRACE("(%p,%p,%ld)",iface,asi,size); + + /* check parameters */ + if (asi == NULL) + return AVIERR_BADPARAM; + if (size != sizeof(AVISTREAMINFOW)) + return AVIERR_BADSIZE; + if (asi->dwScale == 0 || asi->dwRate == 0 || (LONG)asi->dwQuality < -1 || + asi->dwQuality > ICQUALITY_HIGH) + return AVIERR_ERROR; + + This->sInfo.wLanguage = asi->wLanguage; + This->sInfo.wPriority = asi->wPriority; + This->sInfo.dwStart = asi->dwStart; + if (asi->dwRate != 0) + This->sInfo.dwRate = asi->dwRate; + if (asi->dwScale != 0) + This->sInfo.dwScale = asi->dwScale; + if (asi->dwQuality <= ICQUALITY_HIGH) + This->sInfo.dwQuality = ICQUALITY_HIGH; + CopyRect(&This->sInfo.rcFrame, &asi->rcFrame); + memcpy(&This->sInfo.szName, &asi->szName, sizeof(asi->szName)); + This->sInfo.dwEditCount++; + + return AVIERR_OK; +} + +static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface, + REFIID refiid,LPVOID*obj) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae,refiid,obj); +} + +static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_AddRef((IAVIEditStream*)This->pae); +} + +static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_Release((IAVIEditStream*)This->pae); +} + +static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface, + LPARAM lParam1,LPARAM lParam2) +{ + IAVIEditStreamImpl *This = ((IEditAVIStreamImpl*)iface)->pae; + + if (lParam2 != 0) + return AVIERR_ERROR; + + if (This->pStreams == NULL) { + This->pStreams = + GlobalAllocPtr(GMEM_SHARE|GHND, 256 * sizeof(EditStreamTable)); + if (This->pStreams == NULL) + return AVIERR_MEMORY; + This->nTableSize = 256; + } + + if (lParam1 != 0) { + IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo)); + IAVIStream_AddRef((PAVISTREAM)lParam1); + This->pStreams[0].pStream = (PAVISTREAM)lParam1; + This->pStreams[0].dwStart = This->sInfo.dwStart; + This->pStreams[0].dwLength = This->sInfo.dwLength; + This->nStreams = 1; + } + return AVIERR_OK; +} + +static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface, + AVISTREAMINFOW *psi,LONG size) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + TRACE("(%p,%p,%ld)\n",iface,psi,size); + + assert(This->pae != NULL); + + if (psi == NULL) + return AVIERR_BADPARAM; + if (size < 0) + return AVIERR_BADSIZE; + + if (This->pae->bDecompress) + This->pae->sInfo.fccHandler = 0; + + memcpy(psi, &This->pae->sInfo, min((DWORD)size, sizeof(This->pae->sInfo))); + + if ((DWORD)size < sizeof(This->pae->sInfo)) + return AVIERR_BUFFERTOOSMALL; + return AVIERR_OK; +} + +static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos, + LONG flags) +{ + IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae; + PAVISTREAM stream; + DWORD streamPos, streamNr; + + TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags); + + if (flags & FIND_FROM_START) + pos = (LONG)This->sInfo.dwStart; + + /* outside of stream? */ + if (pos < (LONG)This->sInfo.dwStart || + (LONG)This->sInfo.dwStart + (LONG)This->sInfo.dwLength <= pos) + return -1; + + /* map our position to a stream and position in it */ + if (AVIFILE_FindStreamInTable(This, pos, &stream, &streamPos, + &streamNr, TRUE)) + return -1; /* doesn't exist */ + + if (This->bDecompress) { + /* only one stream -- format changes only at start */ + if (flags & FIND_FORMAT) + return (flags & FIND_NEXT ? -1 : 0); + + /* FIXME: map positions back to us */ + return IAVIStream_FindSample(stream, streamPos, flags); + } else { + /* assume change of format every frame */ + return pos; + } +} + +static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos, + LPVOID format,LONG*fmtsize) +{ + IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae; + LPBITMAPINFOHEADER lp; + PAVISTREAM stream; + DWORD n; + HRESULT hr; + + TRACE("(%p,%ld,%p,%p)\n",iface,pos,format,fmtsize); + + if (fmtsize == NULL || pos < This->sInfo.dwStart || + This->sInfo.dwStart + This->sInfo.dwLength <= pos) + return AVIERR_BADPARAM; + + /* find stream corresponding to position */ + hr = AVIFILE_FindStreamInTable(This, pos, &stream, &n, NULL, FALSE); + if (FAILED(hr)) + return hr; + + if (! This->bDecompress) + return IAVIStream_ReadFormat(stream, n, format, fmtsize); + + lp = (LPBITMAPINFOHEADER)AVIFILE_ReadFrame(This, stream, n); + if (lp == NULL) + return AVIERR_ERROR; + if (lp->biBitCount <= 8) { + n = (lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount); + n *= sizeof(RGBQUAD); + } else + n = 0; + n += lp->biSize; + + memcpy(format, lp, min((LONG)n, *fmtsize)); + hr = ((LONG)n > *fmtsize ? AVIERR_BUFFERTOOSMALL : AVIERR_OK); + *fmtsize = n; + + return hr; +} + +static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos, + LPVOID format,LONG formatsize) +{ + TRACE("(%p,%ld,%p,%ld)\n",iface,pos,format,formatsize); + + return AVIERR_UNSUPPORTED; +} + +static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start, + LONG samples,LPVOID buffer, + LONG buffersize,LONG*bytesread, + LONG*samplesread) +{ + IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae; + PAVISTREAM stream; + DWORD streamPos, streamNr; + LONG readBytes, readSamples, count; + HRESULT hr; + + TRACE("(%p,%ld,%ld,%p,%ld,%p,%p) -- 0x%08lX\n",iface,start,samples, + buffer,buffersize,bytesread,samplesread,This->sInfo.fccType); + + /* check parameters */ + if (bytesread != NULL) + *bytesread = 0; + if (samplesread != NULL) + *samplesread = 0; + if (buffersize < 0) + return AVIERR_BADSIZE; + if ((DWORD)start < This->sInfo.dwStart || + This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start) + return AVIERR_BADPARAM; + + if (! This->bDecompress) { + /* audio like data -- sample-based */ + do { + if (samples == 0) + return AVIERR_OK; /* nothing at all or already done */ + + if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream, + &streamPos, &streamNr, FALSE))) + return AVIERR_ERROR; + + /* limit to end of the stream */ + count = samples; + if (streamPos + count > EditStreamEnd(This, streamNr)) + count = EditStreamEnd(This, streamNr) - streamPos; + + hr = IAVIStream_Read(stream, streamPos, count, buffer, buffersize, + &readBytes, &readSamples); + if (FAILED(hr)) + return hr; + if (readBytes == 0 && readSamples == 0 && count != 0) + return AVIERR_FILEREAD; /* for bad stream implementations */ + + if (samplesread != NULL) + *samplesread += readSamples; + if (bytesread != NULL) + *bytesread += readBytes; + if (buffer != NULL) { + (LPBYTE)buffer += readBytes; + buffersize -= readBytes; + } + start += count; + samples -= count; + } while (This->sInfo.dwStart + This->sInfo.dwLength > start); + } else { + /* video like data -- frame-based */ + LPBITMAPINFOHEADER lp; + + if (samples == 0) + return AVIERR_OK; + + if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream, + &streamPos, &streamNr, FALSE))) + return AVIERR_ERROR; + + lp = AVIFILE_ReadFrame(This, stream, streamPos); + if (lp == NULL) + return AVIERR_ERROR; + + if (buffer != NULL) { + /* need size of format to skip */ + if (lp->biBitCount <= 8) { + count = lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount; + count *= sizeof(RGBQUAD); + } else + count = 0; + count += lp->biSize; + + if (buffersize < lp->biSizeImage) + return AVIERR_BUFFERTOOSMALL; + memcpy(buffer, (LPBYTE)lp + count, lp->biSizeImage); + } + + if (bytesread != NULL) + *bytesread = lp->biSizeImage; + if (samplesread != NULL) + *samplesread = 1; + } + + return AVIERR_OK; +} + +static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start, + LONG samples,LPVOID buffer, + LONG buffersize,DWORD flags, + LONG*sampwritten,LONG*byteswritten) +{ + TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)",iface,start,samples,buffer, + buffersize,flags,sampwritten,byteswritten); + + /* be sure return parameters have correct values */ + if (sampwritten != NULL) + *sampwritten = 0; + if (byteswritten != NULL) + *byteswritten = 0; + + return AVIERR_UNSUPPORTED; +} + +static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start, + LONG samples) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + TRACE("(%p,%ld,%ld)\n",iface,start,samples); + + return IAVIEditStream_Cut((IAVIEditStream*)This->pae,&start,&samples,NULL); +} + +static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc, + LPVOID lp,LONG *lpread) +{ + IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae; + DWORD n; + + TRACE("(%p,0x%08lX,%p,%p)",iface,fcc,lp,lpread); + + /* check parameters */ + if (lp == NULL || lpread == NULL) + return AVIERR_BADPARAM; + + /* simply ask every stream and return the first block found */ + for (n = 0; n < This->nStreams; n++) { + HRESULT hr = IAVIStream_ReadData(This->pStreams[n].pStream,fcc,lp,lpread); + + if (SUCCEEDED(hr)) + return hr; + } + + *lpread = 0; + return AVIERR_NODATA; +} + +static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc, + LPVOID lp,LONG size) +{ + TRACE("(%p,0x%08lX,%p,%ld)",iface,fcc,lp,size); + + return AVIERR_UNSUPPORTED; +} + +static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface, + AVISTREAMINFOW*info,LONG len) +{ + ICOM_THIS(IEditAVIStreamImpl,iface); + + TRACE("(%p,%p,%ld)\n",iface,info,len); + + return IAVIEditStream_SetInfo((IAVIEditStream*)This->pae,info,len); +} + +static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj) +{ + ICOM_THIS(IEditStreamInternalImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae, refiid, obj); +} + +static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface) +{ + ICOM_THIS(IEditStreamInternalImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_AddRef((IAVIEditStream*)This->pae); +} + +static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface) +{ + ICOM_THIS(IEditStreamInternalImpl,iface); + + assert(This->pae != NULL); + + return IAVIEditStream_Release((IAVIEditStream*)This->pae); +} + +static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl) +{ + ICOM_THIS(IEditStreamInternalImpl,iface); + + assert(This->pae != NULL); + assert(ppimpl != NULL); + + *ppimpl = This->pae; + return AVIERR_OK; +}