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 DllCanUnloadNow()
|
||||||
@ stdcall -private DllGetClassObject(ptr ptr ptr)
|
@ stdcall -private DllGetClassObject(ptr ptr ptr) STRMBASE_DllGetClassObject
|
||||||
@ stdcall -private DllRegisterServer()
|
@ stdcall -private DllRegisterServer()
|
||||||
@ stdcall -private DllUnregisterServer()
|
@ stdcall -private DllUnregisterServer()
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
||||||
|
|
||||||
static LONG objects_ref = 0;
|
static LONG objects_ref = 0;
|
||||||
static LONG server_locks = 0;
|
|
||||||
|
|
||||||
static const WCHAR wAudioCaptFilter[] =
|
static const WCHAR wAudioCaptFilter[] =
|
||||||
{'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
|
{'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
|
||||||
|
@ -181,157 +180,9 @@ HRESULT WINAPI DllCanUnloadNow(void)
|
||||||
{
|
{
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
if (objects_ref == 0 && server_locks == 0)
|
if (STRMBASE_DllCanUnloadNow() && objects_ref == 0)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
return S_FALSE;
|
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)
|
DWORD ObjectRefCount(BOOL increment)
|
||||||
|
|
|
@ -46,6 +46,7 @@ extern const int g_cTemplates;
|
||||||
extern const FactoryTemplate g_Templates[];
|
extern const FactoryTemplate g_Templates[];
|
||||||
|
|
||||||
static HINSTANCE g_hInst = NULL;
|
static HINSTANCE g_hInst = NULL;
|
||||||
|
static LONG server_locks = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* defines and constants
|
* defines and constants
|
||||||
|
@ -233,3 +234,163 @@ BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
||||||
}
|
}
|
||||||
return TRUE;
|
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 */
|
/* Dll Functions */
|
||||||
BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv);
|
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