strmbase: Implement STRMBASE_DllGetClassObject and STRMBASE_DllCanUnloadNow.
This commit is contained in:
parent
e479273aca
commit
2c3bc2cf56
|
@ -1,4 +1,4 @@
|
|||
@ stdcall -private DllCanUnloadNow()
|
||||
@ stdcall -private DllGetClassObject(ptr ptr ptr)
|
||||
@ stdcall -private DllGetClassObject(ptr ptr ptr) STRMBASE_DllGetClassObject
|
||||
@ stdcall -private DllRegisterServer()
|
||||
@ stdcall -private DllUnregisterServer()
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
||||
|
||||
static LONG objects_ref = 0;
|
||||
static LONG server_locks = 0;
|
||||
|
||||
static const WCHAR wAudioCaptFilter[] =
|
||||
{'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
|
||||
|
@ -181,159 +180,11 @@ HRESULT WINAPI DllCanUnloadNow(void)
|
|||
{
|
||||
TRACE("\n");
|
||||
|
||||
if (objects_ref == 0 && server_locks == 0)
|
||||
if (STRMBASE_DllCanUnloadNow() && objects_ref == 0)
|
||||
return S_OK;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* DLL ClassFactory
|
||||
*/
|
||||
typedef struct {
|
||||
IClassFactory ITF_IClassFactory;
|
||||
|
||||
LONG ref;
|
||||
LPFNNewCOMObject pfnCreateInstance;
|
||||
} IClassFactoryImpl;
|
||||
|
||||
static HRESULT WINAPI
|
||||
DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||
IsEqualGUID(riid, &IID_IClassFactory))
|
||||
{
|
||||
IClassFactory_AddRef(iface);
|
||||
*ppobj = This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid), ppobj);
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
if (ref == 0)
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
|
||||
REFIID riid, LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
HRESULT hres = ERROR_SUCCESS;
|
||||
LPUNKNOWN punk;
|
||||
|
||||
TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
|
||||
|
||||
if (!ppobj)
|
||||
return E_POINTER;
|
||||
|
||||
/* Enforce the normal OLE rules regarding interfaces and delegation */
|
||||
if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppobj = NULL;
|
||||
punk = This->pfnCreateInstance(pOuter, &hres);
|
||||
if (!punk)
|
||||
{
|
||||
/* No object created, update error if it isn't done already and return */
|
||||
if (SUCCEEDED(hres))
|
||||
hres = E_OUTOFMEMORY;
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
hres = IUnknown_QueryInterface(punk, riid, ppobj);
|
||||
}
|
||||
/* Releasing the object. If everything was successful, QueryInterface
|
||||
should have incremented the refcount once more, otherwise this will
|
||||
purge the object. */
|
||||
IUnknown_Release(punk);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
TRACE("(%p)->(%d)\n",This, dolock);
|
||||
|
||||
if (dolock)
|
||||
InterlockedIncrement(&server_locks);
|
||||
else
|
||||
InterlockedDecrement(&server_locks);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IClassFactoryVtbl DSCF_Vtbl =
|
||||
{
|
||||
DSCF_QueryInterface,
|
||||
DSCF_AddRef,
|
||||
DSCF_Release,
|
||||
DSCF_CreateInstance,
|
||||
DSCF_LockServer
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* DllGetClassObject (QCAP.@)
|
||||
*/
|
||||
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
const FactoryTemplate *pList = g_Templates;
|
||||
IClassFactoryImpl *factory;
|
||||
int i;
|
||||
|
||||
TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
|
||||
if (!ppv)
|
||||
return E_POINTER;
|
||||
|
||||
*ppv = NULL;
|
||||
|
||||
if (!IsEqualGUID(&IID_IClassFactory, riid) &&
|
||||
!IsEqualGUID(&IID_IUnknown, riid))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
for (i = 0; i < g_cTemplates; i++, pList++)
|
||||
{
|
||||
if (IsEqualGUID(pList->m_ClsID, rclsid))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == g_cTemplates)
|
||||
{
|
||||
FIXME("%s: no class found.\n", debugstr_guid(rclsid));
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl));
|
||||
if (!factory)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
|
||||
factory->ref = 1;
|
||||
|
||||
factory->pfnCreateInstance = pList->m_lpfnNew;
|
||||
|
||||
*ppv = &(factory->ITF_IClassFactory);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD ObjectRefCount(BOOL increment)
|
||||
{
|
||||
if (increment)
|
||||
|
|
|
@ -46,6 +46,7 @@ extern const int g_cTemplates;
|
|||
extern const FactoryTemplate g_Templates[];
|
||||
|
||||
static HINSTANCE g_hInst = NULL;
|
||||
static LONG server_locks = 0;
|
||||
|
||||
/*
|
||||
* defines and constants
|
||||
|
@ -233,3 +234,163 @@ BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* DLL ClassFactory
|
||||
*/
|
||||
typedef struct {
|
||||
IClassFactory ITF_IClassFactory;
|
||||
|
||||
LONG ref;
|
||||
LPFNNewCOMObject pfnCreateInstance;
|
||||
} IClassFactoryImpl;
|
||||
|
||||
static HRESULT WINAPI
|
||||
DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||
IsEqualGUID(riid, &IID_IClassFactory))
|
||||
{
|
||||
IClassFactory_AddRef(iface);
|
||||
*ppobj = This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid), ppobj);
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
if (ref == 0)
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
|
||||
REFIID riid, LPVOID *ppobj)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
HRESULT hres = ERROR_SUCCESS;
|
||||
LPUNKNOWN punk;
|
||||
|
||||
TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
|
||||
|
||||
if (!ppobj)
|
||||
return E_POINTER;
|
||||
|
||||
/* Enforce the normal OLE rules regarding interfaces and delegation */
|
||||
if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppobj = NULL;
|
||||
punk = This->pfnCreateInstance(pOuter, &hres);
|
||||
if (!punk)
|
||||
{
|
||||
/* No object created, update error if it isn't done already and return */
|
||||
if (SUCCEEDED(hres))
|
||||
hres = E_OUTOFMEMORY;
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
hres = IUnknown_QueryInterface(punk, riid, ppobj);
|
||||
}
|
||||
/* Releasing the object. If everything was successful, QueryInterface
|
||||
should have incremented the refcount once more, otherwise this will
|
||||
purge the object. */
|
||||
IUnknown_Release(punk);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
|
||||
{
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
TRACE("(%p)->(%d)\n",This, dolock);
|
||||
|
||||
if (dolock)
|
||||
InterlockedIncrement(&server_locks);
|
||||
else
|
||||
InterlockedDecrement(&server_locks);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IClassFactoryVtbl DSCF_Vtbl =
|
||||
{
|
||||
DSCF_QueryInterface,
|
||||
DSCF_AddRef,
|
||||
DSCF_Release,
|
||||
DSCF_CreateInstance,
|
||||
DSCF_LockServer
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* DllGetClassObject
|
||||
*/
|
||||
HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
const FactoryTemplate *pList = g_Templates;
|
||||
IClassFactoryImpl *factory;
|
||||
int i;
|
||||
|
||||
TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
|
||||
if (!ppv)
|
||||
return E_POINTER;
|
||||
|
||||
*ppv = NULL;
|
||||
|
||||
if (!IsEqualGUID(&IID_IClassFactory, riid) &&
|
||||
!IsEqualGUID(&IID_IUnknown, riid))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
for (i = 0; i < g_cTemplates; i++, pList++)
|
||||
{
|
||||
if (IsEqualGUID(pList->m_ClsID, rclsid))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == g_cTemplates)
|
||||
{
|
||||
FIXME("%s: no class found.\n", debugstr_guid(rclsid));
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl));
|
||||
if (!factory)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
|
||||
factory->ref = 1;
|
||||
|
||||
factory->pfnCreateInstance = pList->m_lpfnNew;
|
||||
|
||||
*ppv = &(factory->ITF_IClassFactory);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllCanUnloadNow
|
||||
*/
|
||||
HRESULT WINAPI STRMBASE_DllCanUnloadNow(void)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
if (server_locks == 0)
|
||||
return S_OK;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
|
|
@ -315,3 +315,5 @@ HRESULT WINAPI AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER const * pFil
|
|||
|
||||
/* Dll Functions */
|
||||
BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv);
|
||||
HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
|
||||
HRESULT WINAPI STRMBASE_DllCanUnloadNow(void);
|
||||
|
|
Loading…
Reference in New Issue