Commit 8e9cacf0 authored by Michael Stefaniuc's avatar Michael Stefaniuc Committed by Alexandre Julliard

avifil32: Support COM aggregation in WAVFile.

parent 3815c1e9
...@@ -59,7 +59,7 @@ DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0); ...@@ -59,7 +59,7 @@ DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0);
extern HMODULE AVIFILE_hModule DECLSPEC_HIDDEN; extern HMODULE AVIFILE_hModule DECLSPEC_HIDDEN;
extern HRESULT AVIFILE_CreateAVIFile(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN; extern HRESULT AVIFILE_CreateAVIFile(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern HRESULT AVIFILE_CreateWAVFile(REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN; extern HRESULT AVIFILE_CreateWAVFile(IUnknown *outer_unk, REFIID riid, void **ret_iface) DECLSPEC_HIDDEN;
extern HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN; extern HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN; extern HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream) DECLSPEC_HIDDEN; extern PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream) DECLSPEC_HIDDEN;
......
...@@ -149,14 +149,14 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface, ...@@ -149,14 +149,14 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,
if (IsEqualGUID(&CLSID_AVIFile, &This->clsid)) if (IsEqualGUID(&CLSID_AVIFile, &This->clsid))
return AVIFILE_CreateAVIFile(pOuter, riid, ppobj); return AVIFILE_CreateAVIFile(pOuter, riid, ppobj);
if (IsEqualGUID(&CLSID_WAVFile, &This->clsid))
return AVIFILE_CreateWAVFile(pOuter, riid, ppobj);
if (pOuter) if (pOuter)
return CLASS_E_NOAGGREGATION; return CLASS_E_NOAGGREGATION;
if (IsEqualGUID(&CLSID_ICMStream, &This->clsid)) if (IsEqualGUID(&CLSID_ICMStream, &This->clsid))
return AVIFILE_CreateICMStream(riid,ppobj); return AVIFILE_CreateICMStream(riid,ppobj);
if (IsEqualGUID(&CLSID_WAVFile, &This->clsid))
return AVIFILE_CreateWAVFile(riid,ppobj);
if (IsEqualGUID(&CLSID_ACMStream, &This->clsid)) if (IsEqualGUID(&CLSID_ACMStream, &This->clsid))
return AVIFILE_CreateACMStream(riid,ppobj); return AVIFILE_CreateACMStream(riid,ppobj);
......
...@@ -185,6 +185,8 @@ typedef struct _IAVIStreamImpl { ...@@ -185,6 +185,8 @@ typedef struct _IAVIStreamImpl {
struct _IAVIFileImpl { struct _IAVIFileImpl {
IAVIFile IAVIFile_iface; IAVIFile IAVIFile_iface;
IUnknown IUnknown_inner;
IUnknown *outer_unk;
LONG ref; LONG ref;
/* IAVIFile, IAVIStream stuff... */ /* IAVIFile, IAVIStream stuff... */
...@@ -214,29 +216,109 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This); ...@@ -214,29 +216,109 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This);
static HRESULT AVIFILE_LoadSunFile(IAVIFileImpl *This); static HRESULT AVIFILE_LoadSunFile(IAVIFileImpl *This);
static HRESULT AVIFILE_SaveFile(const IAVIFileImpl *This); static HRESULT AVIFILE_SaveFile(const IAVIFileImpl *This);
HRESULT AVIFILE_CreateWAVFile(REFIID riid, LPVOID *ppv) static inline IAVIFileImpl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, IAVIFileImpl, IUnknown_inner);
}
static HRESULT WINAPI IUnknown_fnQueryInterface(IUnknown *iface, REFIID riid, void **ret_iface)
{
IAVIFileImpl *This = impl_from_IUnknown(iface);
TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ret_iface);
if (IsEqualGUID(&IID_IUnknown, riid))
*ret_iface = &This->IUnknown_inner;
else if (IsEqualGUID(&IID_IAVIFile, riid))
*ret_iface = &This->IAVIFile_iface;
else if (IsEqualGUID(&IID_IAVIStream, riid))
*ret_iface = &This->iAVIStream;
else if (IsEqualGUID(&IID_IPersistFile, riid))
*ret_iface = &This->iPersistFile;
else {
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ret_iface);
*ret_iface = NULL;
return E_NOINTERFACE;
}
/* Violation of the COM aggregation ref counting rule */
IUnknown_AddRef(&This->IUnknown_inner);
return S_OK;
}
static ULONG WINAPI IUnknown_fnAddRef(IUnknown *iface)
{
IAVIFileImpl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI IUnknown_fnRelease(IUnknown *iface)
{
IAVIFileImpl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if (!ref) {
/* need to write headers to file */
if (This->fDirty)
AVIFILE_SaveFile(This);
HeapFree(GetProcessHeap(), 0, This->lpFormat);
This->lpFormat = NULL;
This->cbFormat = 0;
HeapFree(GetProcessHeap(), 0, This->extra.lp);
This->extra.lp = NULL;
This->extra.cb = 0;
HeapFree(GetProcessHeap(), 0, This->szFileName);
This->szFileName = NULL;
if (This->hmmio) {
mmioClose(This->hmmio, 0);
This->hmmio = NULL;
}
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static const IUnknownVtbl unk_vtbl =
{
IUnknown_fnQueryInterface,
IUnknown_fnAddRef,
IUnknown_fnRelease
};
HRESULT AVIFILE_CreateWAVFile(IUnknown *outer_unk, REFIID riid, void **ret_iface)
{ {
IAVIFileImpl *pfile; IAVIFileImpl *pfile;
HRESULT hr; HRESULT hr;
assert(riid != NULL && ppv != NULL); *ret_iface = NULL;
*ppv = NULL;
pfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIFileImpl)); pfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIFileImpl));
if (pfile == NULL) if (pfile == NULL)
return AVIERR_MEMORY; return AVIERR_MEMORY;
pfile->IUnknown_inner.lpVtbl = &unk_vtbl;
pfile->IAVIFile_iface.lpVtbl = &iwavft; pfile->IAVIFile_iface.lpVtbl = &iwavft;
pfile->iPersistFile.lpVtbl = &iwavpft; pfile->iPersistFile.lpVtbl = &iwavpft;
pfile->iAVIStream.lpVtbl = &iwavst; pfile->iAVIStream.lpVtbl = &iwavst;
pfile->ref = 0; pfile->ref = 1;
if (outer_unk)
pfile->outer_unk = outer_unk;
else
pfile->outer_unk = &pfile->IUnknown_inner;
pfile->iPersistFile.paf = pfile; pfile->iPersistFile.paf = pfile;
pfile->iAVIStream.paf = pfile; pfile->iAVIStream.paf = pfile;
hr = IAVIFile_QueryInterface((IAVIFile*)pfile, riid, ppv); hr = IUnknown_QueryInterface(&pfile->IUnknown_inner, riid, ret_iface);
if (FAILED(hr)) IUnknown_Release(&pfile->IUnknown_inner);
HeapFree(GetProcessHeap(), 0, pfile);
return hr; return hr;
} }
...@@ -246,74 +328,25 @@ static inline IAVIFileImpl *impl_from_IAVIFile(IAVIFile *iface) ...@@ -246,74 +328,25 @@ static inline IAVIFileImpl *impl_from_IAVIFile(IAVIFile *iface)
return CONTAINING_RECORD(iface, IAVIFileImpl, IAVIFile_iface); return CONTAINING_RECORD(iface, IAVIFileImpl, IAVIFile_iface);
} }
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile *iface, REFIID refiid, static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile *iface, REFIID riid, void **ret_iface)
LPVOID *obj)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IAVIFile(iface);
TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj); return IUnknown_QueryInterface(This->outer_unk, riid, ret_iface);
if (IsEqualGUID(&IID_IUnknown, refiid) ||
IsEqualGUID(&IID_IAVIFile, refiid)) {
*obj = iface;
IAVIFile_AddRef(iface);
return S_OK;
} else if (IsEqualGUID(&IID_IAVIStream, refiid)) {
*obj = &This->iAVIStream;
IAVIFile_AddRef(iface);
return S_OK;
} else if (IsEqualGUID(&IID_IPersistFile, refiid)) {
*obj = &This->iPersistFile;
IAVIFile_AddRef(iface);
return S_OK;
}
return OLE_E_ENUM_NOMORE;
} }
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface) static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IAVIFile(iface);
TRACE("(%p)\n",iface); return IUnknown_AddRef(This->outer_unk);
return InterlockedIncrement(&This->ref);
} }
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface) static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IAVIFile(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)\n",iface); return IUnknown_Release(This->outer_unk);
if (!ref) {
if (This->fDirty) {
/* need to write headers to file */
AVIFILE_SaveFile(This);
}
if (This->lpFormat != NULL) {
HeapFree(GetProcessHeap(), 0, This->lpFormat);
This->lpFormat = NULL;
This->cbFormat = 0;
}
if (This->extra.lp != NULL) {
HeapFree(GetProcessHeap(), 0, This->extra.lp);
This->extra.lp = NULL;
This->extra.cb = 0;
}
HeapFree(GetProcessHeap(), 0, This->szFileName);
This->szFileName = NULL;
if (This->hmmio != NULL) {
mmioClose(This->hmmio, 0);
This->hmmio = NULL;
}
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
return ref;
} }
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, AVIFILEINFOW *afi, LONG size) static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, AVIFILEINFOW *afi, LONG size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment