windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/msconf/clclsfct.cpp
2020-09-26 16:20:57 +08:00

491 lines
11 KiB
C++

/*
* clsfact.cpp - IClassFactory implementation.
*
* Taken from URL code - essentially identical to DavidDi's original code
*
* Created: ChrisPi 9-11-95
*
*/
/* Headers
**********/
#include "precomp.h"
#include "CLinkID.h"
#include "clrefcnt.hpp"
#include "clenumft.hpp"
#include "clCnfLnk.hpp"
#include "clclsfct.h"
#define INITGUID
#include <initguid.h>
#include <olectlid.h>
#include <confguid.h>
// from niMgr.cpp
PIUnknown NewNmManager(OBJECTDESTROYEDPROC ObjectDestroyed);
// from imconfmg.cpp
PIUnknown NewConfMgr(OBJECTDESTROYEDPROC ObjectDestroyed);
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
CCLASSCONSTRUCTOR s_cclscnstr[] =
{
// { &CLSID_ConferenceManager, &NewNmManager },
{ &CLSID_ConfLink, &NewConfLink },
// { &CLSID_NmManager, &NewNmManager },
// { &CLSID_MIMEFileTypesPropSheetHook, &NewMIMEHook },
// { &CLSID_Internet, &NewInternet },
};
#pragma data_seg()
/* Module Variables
*******************/
#pragma data_seg(DATA_SEG_PER_INSTANCE)
// DLL reference count == number of class factories +
// number of URLs +
// LockServer() count
ULONG s_ulcDLLRef = 0;
#pragma data_seg()
/***************************** Private Functions *****************************/
HRESULT GetClassConstructor(REFCLSID rclsid,
PNEWOBJECTPROC pNewObject)
{
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
UINT u;
ASSERT(IsValidREFCLSID(rclsid));
ASSERT(IS_VALID_WRITE_PTR(pNewObject, NEWOBJECTPROC));
*pNewObject = NULL;
for (u = 0; u < ARRAY_ELEMENTS(s_cclscnstr); u++)
{
if (rclsid == *(s_cclscnstr[u].pcclsid))
{
*pNewObject = s_cclscnstr[u].NewObject;
hr = S_OK;
}
}
ASSERT((hr == S_OK &&
IS_VALID_CODE_PTR(*pNewObject, NEWOBJECTPROC)) ||
(hr == CLASS_E_CLASSNOTAVAILABLE &&
! *pNewObject));
return(hr);
}
VOID STDMETHODCALLTYPE DLLObjectDestroyed(void)
{
TRACE_OUT(("DLLObjectDestroyed(): Object destroyed."));
DllRelease();
}
PIUnknown NewConfLink(OBJECTDESTROYEDPROC ObjectDestroyed)
{
ASSERT(! ObjectDestroyed ||
IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
TRACE_OUT(("NewConfLink(): Creating a new ConfLink."));
return((PIUnknown) (PIConferenceLink) new CConfLink(ObjectDestroyed));
}
#if 0
PIUnknown NewMIMEHook(OBJECTDESTROYEDPROC ObjectDestroyed)
{
ASSERT(! ObjectDestroyed ||
IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
TRACE_OUT(("NewMIMEHook(): Creating a new MIMEHook."));
return((PIUnknown)(PIShellPropSheetExt)new(MIMEHook(ObjectDestroyed)));
}
PIUnknown NewInternet(OBJECTDESTROYEDPROC ObjectDestroyed)
{
ASSERT(! ObjectDestroyed ||
IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
TRACE_OUT(("NewInternet(): Creating a new Internet."));
return((PIUnknown)(PIShellPropSheetExt)new(Internet(ObjectDestroyed)));
}
#endif // 0
#ifdef DEBUG
BOOL IsValidPCCCLClassFactory(PCCCLClassFactory pccf)
{
return(IS_VALID_READ_PTR(pccf, CCCLClassFactory) &&
IS_VALID_CODE_PTR(pccf->m_NewObject, NEWOBJECTPROC) &&
IS_VALID_STRUCT_PTR((PCRefCount)pccf, CRefCount) &&
IS_VALID_INTERFACE_PTR((PCIClassFactory)pccf, IClassFactory));
}
#endif
/****************************** Public Functions *****************************/
ULONG DLLAddRef(void)
{
ULONG ulcRef;
ASSERT(s_ulcDLLRef < ULONG_MAX);
ulcRef = ++s_ulcDLLRef;
TRACE_OUT(("DLLAddRef(): DLL reference count is now %lu.",
ulcRef));
return(ulcRef);
}
ULONG DLLRelease(void)
{
ULONG ulcRef;
if (EVAL(s_ulcDLLRef > 0))
s_ulcDLLRef--;
ulcRef = s_ulcDLLRef;
TRACE_OUT(("DLLRelease(): DLL reference count is now %lu.",
ulcRef));
return(ulcRef);
}
PULONG GetDLLRefCountPtr(void)
{
return(&s_ulcDLLRef);
}
/********************************** Methods **********************************/
CCLClassFactory::CCLClassFactory(NEWOBJECTPROC NewObject,
OBJECTDESTROYEDPROC ObjectDestroyed) :
RefCount(ObjectDestroyed)
{
DebugEntry(CCLClassFactory::CCLClassFactory);
// Don't validate this until after construction.
ASSERT(IS_VALID_CODE_PTR(NewObject, NEWOBJECTPROC));
m_NewObject = NewObject;
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
DebugExitVOID(CCLClassFactory::CCLClassFactory);
return;
}
CCLClassFactory::~CCLClassFactory(void)
{
DebugEntry(CCLClassFactory::~CCLClassFactory);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
m_NewObject = NULL;
// Don't validate this after destruction.
DebugExitVOID(CCLClassFactory::~CCLClassFactory);
return;
}
ULONG STDMETHODCALLTYPE CCLClassFactory::AddRef(void)
{
ULONG ulcRef;
DebugEntry(CCLClassFactory::AddRef);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
ulcRef = RefCount::AddRef();
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
DebugExitULONG(CCLClassFactory::AddRef, ulcRef);
return(ulcRef);
}
ULONG STDMETHODCALLTYPE CCLClassFactory::Release(void)
{
ULONG ulcRef;
DebugEntry(CCLClassFactory::Release);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
ulcRef = RefCount::Release();
DebugExitULONG(CCLClassFactory::Release, ulcRef);
return(ulcRef);
}
HRESULT STDMETHODCALLTYPE CCLClassFactory::QueryInterface(REFIID riid,
PVOID *ppvObject)
{
HRESULT hr = S_OK;
DebugEntry(CCLClassFactory::QueryInterface);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
ASSERT(IsValidREFIID(riid));
ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
if (riid == IID_IClassFactory)
{
*ppvObject = (PIClassFactory)this;
ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IClassFactory."));
}
else if (riid == IID_IUnknown)
{
*ppvObject = (PIUnknown)this;
ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IUnknown."));
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
TRACE_OUT(("CCLClassFactory::QueryInterface(): Called on unknown interface."));
}
if (hr == S_OK)
AddRef();
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
// removed by ChrisPi CINTERFACE undeclared identifier
// ASSERT(FAILED(hr) ||
// IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
DebugExitHRESULT(CCLClassFactory::QueryInterface, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE CCLClassFactory::CreateInstance(PIUnknown piunkOuter,
REFIID riid,
PVOID *ppvObject)
{
HRESULT hr;
DebugEntry(CCLClassFactory::CreateInstance);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
ASSERT(! piunkOuter ||
IS_VALID_INTERFACE_PTR(piunkOuter, IUnknown));
ASSERT(IsValidREFIID(riid));
ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
*ppvObject = NULL;
if (! piunkOuter)
{
PIUnknown piunk;
piunk = (*m_NewObject)( (void(__stdcall *)(void)) &DLLObjectDestroyed);
if (piunk)
{
DllLock();
hr = piunk->QueryInterface(riid, ppvObject);
// N.b., the Release() method will destroy the object if the
// QueryInterface() method failed.
piunk->Release();
}
else
hr = E_OUTOFMEMORY;
}
else
{
hr = CLASS_E_NOAGGREGATION;
WARNING_OUT(("CCLClassFactory::CreateInstance(): Aggregation not supported."));
}
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
// removed by ChrisPi - see above
// ASSERT(FAILED(hr) ||
// IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
DebugExitHRESULT(CCLClassFactory::CreateInstance, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE CCLClassFactory::LockServer(BOOL bLock)
{
HRESULT hr;
DebugEntry(CCLClassFactory::LockServer);
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
// bLock may be any value.
if (bLock)
DllLock();
else
DllRelease();
hr = S_OK;
ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
DebugExitHRESULT(CCLClassFactory::LockServer, hr);
return(hr);
}
/***************************** Exported Functions ****************************/
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PVOID *ppvObject)
{
HRESULT hr = S_OK;
NEWOBJECTPROC NewObject;
DebugEntry(DllGetClassObject);
ASSERT(IsValidREFCLSID(rclsid));
ASSERT(IsValidREFIID(riid));
ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
*ppvObject = NULL;
hr = GetClassConstructor(rclsid, &NewObject);
if (hr == S_OK)
{
if (riid == IID_IUnknown ||
riid == IID_IClassFactory)
{
PCCLClassFactory pcf;
pcf = new CCLClassFactory(NewObject, (void(__stdcall *)(void)) &DLLObjectDestroyed);
if (pcf)
{
if (riid == IID_IClassFactory)
{
*ppvObject = (PIClassFactory)pcf;
ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
TRACE_OUT(("DllGetClassObject(): Returning IClassFactory."));
}
else
{
ASSERT(riid == IID_IUnknown);
*ppvObject = (PIUnknown)pcf;
ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
TRACE_OUT(("DllGetClassObject(): Returning IUnknown."));
}
DllLock();
hr = S_OK;
TRACE_OUT(("DllGetClassObject(): Created a new class factory."));
}
else
hr = E_OUTOFMEMORY;
}
else
{
WARNING_OUT(("DllGetClassObject(): Called on unknown interface."));
hr = E_NOINTERFACE;
}
}
else
WARNING_OUT(("DllGetClassObject(): Called on unknown class."));
// removed by ChrisPi - see above
// ASSERT(FAILED(hr) ||
// IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
DebugExitHRESULT(DllGetClassObject, hr);
return(hr);
}
STDAPI DllCanUnloadNow(void)
{
HRESULT hr;
DebugEntry(DllCanUnloadNow);
hr = (s_ulcDLLRef > 0) ? S_FALSE : S_OK;
TRACE_OUT(("DllCanUnloadNow(): DLL reference count is %lu.", s_ulcDLLRef));
DebugExitHRESULT(DllCanUnloadNow, hr);
return(hr);
}
void DllLock(void)
{
InterlockedIncrement((LPLONG) &s_ulcDLLRef);
DBGAPI_TRACE("Ref: DllLock count=%d", s_ulcDLLRef);
}
void DllRelease(void)
{
LONG cRef = InterlockedDecrement((LPLONG) &s_ulcDLLRef);
#ifdef DEBUG
DBGAPI_TRACE("Ref: DllLock count=%d", s_ulcDLLRef);
if (0 == cRef)
WARNING_OUT(("MSCONF.DLL Can now be unloaded"));
#endif
}