Commit 7854cce7 authored by Michael Stefaniuc's avatar Michael Stefaniuc Committed by Alexandre Julliard

avifil32: Support COM aggregation for AVIFile.

Ref counting bug in QueryInterface comes free of charge!
parent 39127a07
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
* When index is missing it works, but index seems to be okay. * When index is missing it works, but index seems to be okay.
*/ */
#define COBJMACROS
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
...@@ -118,8 +119,10 @@ typedef struct _IAVIStreamImpl { ...@@ -118,8 +119,10 @@ typedef struct _IAVIStreamImpl {
} IAVIStreamImpl; } IAVIStreamImpl;
struct _IAVIFileImpl { struct _IAVIFileImpl {
IUnknown IUnknown_inner;
IAVIFile IAVIFile_iface; IAVIFile IAVIFile_iface;
IPersistFile IPersistFile_iface; IPersistFile IPersistFile_iface;
IUnknown *outer_unk;
LONG ref; LONG ref;
AVIFILEINFOW fInfo; AVIFILEINFOW fInfo;
...@@ -144,6 +147,11 @@ struct _IAVIFileImpl { ...@@ -144,6 +147,11 @@ struct _IAVIFileImpl {
BOOL fDirty; BOOL fDirty;
}; };
static inline IAVIFileImpl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, IAVIFileImpl, IUnknown_inner);
}
static inline IAVIFileImpl *impl_from_IAVIFile(IAVIFile *iface) static inline IAVIFileImpl *impl_from_IAVIFile(IAVIFile *iface)
{ {
return CONTAINING_RECORD(iface, IAVIFileImpl, IAVIFile_iface); return CONTAINING_RECORD(iface, IAVIFileImpl, IAVIFile_iface);
...@@ -180,32 +188,37 @@ static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block, ...@@ -180,32 +188,37 @@ static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
FOURCC ckid, DWORD flags, LPCVOID buffer, FOURCC ckid, DWORD flags, LPCVOID buffer,
LONG size); LONG size);
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile *iface, REFIID refiid, static HRESULT WINAPI IUnknown_fnQueryInterface(IUnknown *iface, REFIID riid, void **ppv)
LPVOID *obj)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IUnknown(iface);
TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
if (IsEqualGUID(&IID_IUnknown, refiid) || TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
IsEqualGUID(&IID_IAVIFile, refiid)) {
*obj = iface;
IAVIFile_AddRef(iface);
return S_OK; if (!ppv) {
} else if (IsEqualGUID(&IID_IPersistFile, refiid)) { WARN("invalid parameter\n");
*obj = &This->IPersistFile_iface; return E_INVALIDARG;
IAVIFile_AddRef(iface); }
*ppv = NULL;
return S_OK; if (IsEqualIID(riid, &IID_IUnknown))
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_IAVIFile))
*ppv = &This->IAVIFile_iface;
else if (IsEqualGUID(riid, &IID_IPersistFile))
*ppv = &This->IPersistFile_iface;
else {
WARN("unknown IID %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
} }
return E_NOINTERFACE; /* Violation of the COM aggregation ref counting rule */
IUnknown_AddRef(&This->IUnknown_inner);
return S_OK;
} }
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface) static ULONG WINAPI IUnknown_fnAddRef(IUnknown *iface)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedIncrement(&This->ref); ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref); TRACE("(%p) ref=%d\n", This, ref);
...@@ -213,29 +226,26 @@ static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface) ...@@ -213,29 +226,26 @@ static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface)
return ref; return ref;
} }
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface) static ULONG WINAPI IUnknown_fnRelease(IUnknown *iface)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedDecrement(&This->ref); ULONG ref = InterlockedDecrement(&This->ref);
UINT i; UINT i;
TRACE("(%p) ref=%d\n", This, ref); TRACE("(%p) ref=%d\n", This, ref);
if (!ref) { if (!ref) {
if (This->fDirty) { if (This->fDirty)
/* need to write headers to file */
AVIFILE_SaveFile(This); AVIFILE_SaveFile(This);
}
for (i = 0; i < This->fInfo.dwStreams; i++) { for (i = 0; i < This->fInfo.dwStreams; i++) {
if (This->ppStreams[i] != NULL) { if (This->ppStreams[i] != NULL) {
if (This->ppStreams[i]->ref != 0) { if (This->ppStreams[i]->ref != 0)
ERR(": someone has still %u reference to stream %u (%p)!\n", ERR(": someone has still %u reference to stream %u (%p)!\n",
This->ppStreams[i]->ref, i, This->ppStreams[i]); This->ppStreams[i]->ref, i, This->ppStreams[i]);
} AVIFILE_DestructAVIStream(This->ppStreams[i]);
AVIFILE_DestructAVIStream(This->ppStreams[i]); HeapFree(GetProcessHeap(), 0, This->ppStreams[i]);
HeapFree(GetProcessHeap(), 0, This->ppStreams[i]); This->ppStreams[i] = NULL;
This->ppStreams[i] = NULL;
} }
} }
...@@ -264,6 +274,34 @@ static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface) ...@@ -264,6 +274,34 @@ static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface)
return ref; return ref;
} }
static const IUnknownVtbl unk_vtbl =
{
IUnknown_fnQueryInterface,
IUnknown_fnAddRef,
IUnknown_fnRelease
};
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile *iface, REFIID riid, void **ppv)
{
IAVIFileImpl *This = impl_from_IAVIFile(iface);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface)
{
IAVIFileImpl *This = impl_from_IAVIFile(iface);
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface)
{
IAVIFileImpl *This = impl_from_IAVIFile(iface);
return IUnknown_Release(This->outer_unk);
}
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, AVIFILEINFOW *afi, LONG size) static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, AVIFILEINFOW *afi, LONG size)
{ {
IAVIFileImpl *This = impl_from_IAVIFile(iface); IAVIFileImpl *This = impl_from_IAVIFile(iface);
...@@ -485,25 +523,25 @@ static const struct IAVIFileVtbl avif_vt = { ...@@ -485,25 +523,25 @@ static const struct IAVIFileVtbl avif_vt = {
}; };
static HRESULT WINAPI IPersistFile_fnQueryInterface(IPersistFile *iface, REFIID refiid, void **ppv) static HRESULT WINAPI IPersistFile_fnQueryInterface(IPersistFile *iface, REFIID riid, void **ppv)
{ {
IAVIFileImpl *This = impl_from_IPersistFile(iface); IAVIFileImpl *This = impl_from_IPersistFile(iface);
return IAVIFile_QueryInterface(&This->IAVIFile_iface, refiid, ppv); return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
} }
static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile *iface) static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile *iface)
{ {
IAVIFileImpl *This = impl_from_IPersistFile(iface); IAVIFileImpl *This = impl_from_IPersistFile(iface);
return IAVIFile_AddRef(&This->IAVIFile_iface); return IUnknown_AddRef(This->outer_unk);
} }
static ULONG WINAPI IPersistFile_fnRelease(IPersistFile *iface) static ULONG WINAPI IPersistFile_fnRelease(IPersistFile *iface)
{ {
IAVIFileImpl *This = impl_from_IPersistFile(iface); IAVIFileImpl *This = impl_from_IPersistFile(iface);
return IAVIFile_Release(&This->IAVIFile_iface); return IUnknown_Release(This->outer_unk);
} }
static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile *iface, LPCLSID pClassID) static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile *iface, LPCLSID pClassID)
...@@ -634,7 +672,7 @@ static const struct IPersistFileVtbl pf_vt = { ...@@ -634,7 +672,7 @@ static const struct IPersistFileVtbl pf_vt = {
IPersistFile_fnGetCurFile IPersistFile_fnGetCurFile
}; };
HRESULT AVIFILE_CreateAVIFile(REFIID riid, void **ppv) HRESULT AVIFILE_CreateAVIFile(IUnknown *pUnkOuter, REFIID riid, void **ppv)
{ {
IAVIFileImpl *obj; IAVIFileImpl *obj;
HRESULT hr; HRESULT hr;
...@@ -644,13 +682,17 @@ HRESULT AVIFILE_CreateAVIFile(REFIID riid, void **ppv) ...@@ -644,13 +682,17 @@ HRESULT AVIFILE_CreateAVIFile(REFIID riid, void **ppv)
if (!obj) if (!obj)
return AVIERR_MEMORY; return AVIERR_MEMORY;
obj->IUnknown_inner.lpVtbl = &unk_vtbl;
obj->IAVIFile_iface.lpVtbl = &avif_vt; obj->IAVIFile_iface.lpVtbl = &avif_vt;
obj->IPersistFile_iface.lpVtbl = &pf_vt; obj->IPersistFile_iface.lpVtbl = &pf_vt;
obj->ref = 0; obj->ref = 1;
if (pUnkOuter)
hr = IAVIFile_QueryInterface(&obj->IAVIFile_iface, riid, ppv); obj->outer_unk = pUnkOuter;
if (FAILED(hr)) else
HeapFree(GetProcessHeap(), 0, obj); obj->outer_unk = &obj->IUnknown_inner;
hr = IUnknown_QueryInterface(&obj->IUnknown_inner, riid, ppv);
IUnknown_Release(&obj->IUnknown_inner);
return hr; return hr;
} }
......
...@@ -58,7 +58,7 @@ DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0); ...@@ -58,7 +58,7 @@ DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0);
extern HMODULE AVIFILE_hModule DECLSPEC_HIDDEN; extern HMODULE AVIFILE_hModule DECLSPEC_HIDDEN;
extern HRESULT AVIFILE_CreateAVIFile(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(REFIID riid, LPVOID *ppobj) 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;
......
...@@ -140,12 +140,19 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface, ...@@ -140,12 +140,19 @@ static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,
TRACE("(%p,%p,%s,%p)\n", iface, pOuter, debugstr_guid(riid), TRACE("(%p,%p,%s,%p)\n", iface, pOuter, debugstr_guid(riid),
ppobj); ppobj);
if (ppobj == NULL || pOuter != NULL) if (!ppobj)
return E_FAIL; return E_INVALIDARG;
*ppobj = NULL; *ppobj = NULL;
if (pOuter && !IsEqualGUID(&IID_IUnknown, riid))
return E_INVALIDARG;
if (IsEqualGUID(&CLSID_AVIFile, &This->clsid)) if (IsEqualGUID(&CLSID_AVIFile, &This->clsid))
return AVIFILE_CreateAVIFile(riid,ppobj); return AVIFILE_CreateAVIFile(pOuter, riid, ppobj);
if (pOuter)
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)) if (IsEqualGUID(&CLSID_WAVFile, &This->clsid))
......
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