strmbase: Implement STRMBASE_DllGetClassObject and STRMBASE_DllCanUnloadNow.
diff --git a/dlls/strmbase/dllfunc.c b/dlls/strmbase/dllfunc.c
index c24ec97..35e373f 100644
--- a/dlls/strmbase/dllfunc.c
+++ b/dlls/strmbase/dllfunc.c
@@ -46,6 +46,7 @@
extern const FactoryTemplate g_Templates[];
static HINSTANCE g_hInst = NULL;
+static LONG server_locks = 0;
/*
* defines and constants
@@ -233,3 +234,163 @@
}
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;
+}