|
|
//=--------------------------------------------------------------------------=
// ClassFactory.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
// contains the implementation of the ClassFactory object. we support
// IClassFactory and IClassFactory2
//
#include "pch.h"
#include "LocalSrv.H"
#include "ClassF.H"
#include "Unknown.H" // for CREATEFNOFOBJECT
//=--------------------------------------------------------------------------=
// private module level data
//=--------------------------------------------------------------------------=
//
// ASSERT and FAIL require this
//
SZTHISFILE
// private routines for this file
//
HRESULT CreateOleObjectFromIndex(IUnknown *, int Index, void **, REFIID);
// This is the GUID for a "phantom" interface which VB5 UserControls query
// for to determine if the control doesn't require its license key to be
// present if it's part of a composite UserControl being used in the
// design environment.
//
static const GUID IID_ILicOnCompositeCtl = { 0x6e6e9780, 0x165d, 0x11d0, { 0xb3, 0xe6, 0x00, 0xa0, 0xc9, 0x0f, 0x27, 0x31 } };
//=--------------------------------------------------------------------------=
// CClassFactory::CClassFactory
//=--------------------------------------------------------------------------=
// create the object and initialize the refcount
//
// Parameters:
// int - [in] index into our global table of objects for this guy
//
// Notes:
//
CClassFactory::CClassFactory ( int iIndex ) : m_iIndex(iIndex) { InterlockedIncrement(&g_cLocks); m_cRefs = 1; }
//=--------------------------------------------------------------------------=
// CClassFactory::~CClassFactory
//=--------------------------------------------------------------------------=
// "Life levels all men. Death reveals the eminent."
// - George Bernard Shaw (1856 - 1950)
//
// Notes:
//
CClassFactory::~CClassFactory () { ASSERT(m_cRefs == 0, "Object being deleted with refs!"); InterlockedDecrement(&g_cLocks); return; }
//=--------------------------------------------------------------------------=
// CClassFactory::QueryInterface
//=--------------------------------------------------------------------------=
// the user wants another interface. we won't give 'em. very many.
//
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
STDMETHODIMP CClassFactory::QueryInterface ( REFIID riid, void **ppvObjOut ) { void *pv;
CHECK_POINTER(ppvObjOut);
// we support IUnknown, and the two CF interfaces
//
if (DO_GUIDS_MATCH(riid, IID_IClassFactory)) { pv = (void *)(IClassFactory *)this; } else if (DO_GUIDS_MATCH(riid, IID_IClassFactory2)) { pv = (void *)(IClassFactory2 *)this; } else if (DO_GUIDS_MATCH(riid, IID_IUnknown)) { pv = (void *)(IUnknown *)this; } else if (g_fUseRuntimeLicInCompositeCtl && riid == IID_ILicOnCompositeCtl) { pv = (void *)(IUnknown *)this; } else { *ppvObjOut = NULL; return E_NOINTERFACE; }
((IUnknown *)pv)->AddRef(); *ppvObjOut = pv; return S_OK; }
//=--------------------------------------------------------------------------=
// CClassFactory::AddRef
//=--------------------------------------------------------------------------=
// adds a tick to the current reference count.
//
// Output:
// ULONG - the new reference count
//
// Notes:
//
ULONG CClassFactory::AddRef ( void ) { return ++m_cRefs; }
//=--------------------------------------------------------------------------=
// CClassFactory::Release
//=--------------------------------------------------------------------------=
// removes a tick from the count, and delets the object if necessary
//
// Output:
// ULONG - remaining refs
//
// Notes:
//
ULONG CClassFactory::Release ( void ) { ASSERT(m_cRefs, "No Refs, and we're being released!"); if(--m_cRefs) return m_cRefs;
delete this; return 0; }
//=--------------------------------------------------------------------------=
// CClassFactory::CreateInstance
//=--------------------------------------------------------------------------=
// create an instance of some sort of object.
//
// Parameters:
// IUnknown * - [in] controlling IUknonwn for aggregation
// REFIID - [in] interface id for new object
// void ** - [out] pointer to new interface object.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE, E_UNEXPECTED,
// E_OUTOFMEMORY, E_INVALIDARG
//
// Notes:
//
STDMETHODIMP CClassFactory::CreateInstance ( IUnknown *pUnkOuter, REFIID riid, void **ppvObjOut ) { // check args
//
if (!ppvObjOut) return E_INVALIDARG;
// check to see if we've done our licensing work. we do this as late
// as possible that people calling CreateInstanceLic don't suffer from
// a performance hit here.
//
// crit sect this for apartment threading, since it's global
//
ENTERCRITICALSECTION1(&g_CriticalSection); if (!g_fCheckedForLicense) { g_fMachineHasLicense = CheckForLicense(); g_fCheckedForLicense = TRUE; } LEAVECRITICALSECTION1(&g_CriticalSection);
// check to see if they have the appropriate license to create this stuff
//
if (!g_fMachineHasLicense) return CLASS_E_NOTLICENSED;
// try to create one of the objects that we support
//
return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid); }
//=--------------------------------------------------------------------------=
// CClassFactory::LockServer
//=--------------------------------------------------------------------------=
// lock the server so we can't unload
//
// Parameters:
// BOOL - [in] TRUE means addref, false means release lock count.
//
// Output:
// HRESULT - S_OK, E_FAIL, E_OUTOFMEMORY, E_UNEXPECTED
//
// Notes:
//
STDMETHODIMP CClassFactory::LockServer ( BOOL fLock ) { // update the lock count. crit sect these in case of another thread.
//
if (fLock) InterlockedIncrement(&g_cLocks); else { ASSERT(g_cLocks, "D'oh! Lock Counting Problem"); InterlockedDecrement(&g_cLocks); }
return S_OK; }
//=--------------------------------------------------------------------------=
// CClassFactory::GetLicInfo
//=--------------------------------------------------------------------------=
// IClassFactory2 GetLicInfo
//
// Parameters:
// LICINFO * - unclear
//
// Output:
// HRESULT - unclear
//
// Notes:
//
STDMETHODIMP CClassFactory::GetLicInfo ( LICINFO *pLicInfo ) { CHECK_POINTER(pLicInfo);
// crit sect this for apartment threading, since it's global
//
ENTERCRITICALSECTION1(&g_CriticalSection); if (!g_fCheckedForLicense) { g_fMachineHasLicense = CheckForLicense(); g_fCheckedForLicense = TRUE; } LEAVECRITICALSECTION1(&g_CriticalSection);
// This says whether RequestLicKey will work
//
pLicInfo->fRuntimeKeyAvail = g_fMachineHasLicense;
// This says whether the standard CreateInstance will work
//
pLicInfo->fLicVerified = g_fMachineHasLicense;
return S_OK; }
//=--------------------------------------------------------------------------=
// CClassFactory::RequestLicKey
//=--------------------------------------------------------------------------=
// IClassFactory2 RequestLicKey
//
// Parameters:
// DWORD - [in] reserved
// BSTR * - [out] unclear
//
// Output:
// HRESULT - unclear
//
// Notes:
//
STDMETHODIMP CClassFactory::RequestLicKey ( DWORD dwReserved, BSTR *pbstr ) { // crit sect this for apartment threading, since it's global
//
ENTERCRITICALSECTION1(&g_CriticalSection); if (!g_fCheckedForLicense) { g_fMachineHasLicense = CheckForLicense(); g_fCheckedForLicense = TRUE; } LEAVECRITICALSECTION1(&g_CriticalSection);
// if the machine isn't licensed, then we're not about to give this to them !
//
if (!g_fMachineHasLicense) return CLASS_E_NOTLICENSED;
*pbstr = GetLicenseKey(); return (*pbstr) ? S_OK : E_OUTOFMEMORY; }
//=--------------------------------------------------------------------------=
// CClassFactory::CreateInstanceLic
//=--------------------------------------------------------------------------=
// create a new instance given a licensing key, etc ...
//
// Parameters:
// IUnknown * - [in] controlling IUnknown for aggregation
// IUnknown * - [in] reserved, must be NULL
// REFIID - [in] IID We're looking for.
// BSTR - [in] license key
// void ** - [out] where to put the new object.
//
// Output:
// HRESULT - unclear
//
// Notes:
//
STDMETHODIMP CClassFactory::CreateInstanceLic ( IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID riid, BSTR bstrKey, void **ppvObjOut ) { *ppvObjOut = NULL;
// crit sect this for apartment threading, since it's global
//
ENTERCRITICALSECTION1(&g_CriticalSection); if (!g_fCheckedForLicense) { g_fMachineHasLicense = CheckForLicense(); g_fCheckedForLicense = TRUE; } LEAVECRITICALSECTION1(&g_CriticalSection);
// go and see if the key they gave us matches.
//
if (!CheckLicenseKey(bstrKey)) return CLASS_E_NOTLICENSED;
// if it does, then go and create the object.
//
return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid); }
//=--------------------------------------------------------------------------=
// CreateOleObjectFromIndex
//=--------------------------------------------------------------------------=
// given an index in our object table, create an object from it.
//
// Parameters:
// IUnknown * - [in] Controlling Unknown, if any, for aggregation
// int - [in] index into our global table
// void ** - [out] where to put resulting object.
// REFIID - [in] the interface they want resulting object to be.
//
// Output:
// HRESULT - S_OK, E_OUTOFMEMORY, E_NOINTERFACE
//
// Notes:
//
HRESULT CreateOleObjectFromIndex ( IUnknown *pUnkOuter, int iIndex, void **ppvObjOut, REFIID riid ) { IUnknown *pUnk = NULL; HRESULT hr;
// If the object specifies a pre-Create static function call that first.
//
if (PRECREATEFNOFOBJECT(iIndex) != NULL) { hr = PRECREATEFNOFOBJECT(iIndex)(); IfFailRet(hr); } // go and create the object
//
ASSERT(CREATEFNOFOBJECT(iIndex), "WARNING: Attempt to create an object that doesn't have a Create function."); if (!CREATEFNOFOBJECT(iIndex)) return E_FAIL;
pUnk = CREATEFNOFOBJECT(iIndex)(pUnkOuter);
// sanity check and make sure the object actually got allocated.
//
RETURN_ON_NULLALLOC(pUnk);
// make sure we support aggregation here properly -- if they gave us
// a controlling unknown, then they -must- ask for IUnknown, and we'll
// give them the private unknown the object gave us.
//
if (pUnkOuter) { if (!DO_GUIDS_MATCH(riid, IID_IUnknown)) { pUnk->Release(); return E_INVALIDARG; }
*ppvObjOut = (void *)pUnk; hr = S_OK; } else {
// QI for whatever the user wants.
//
hr = pUnk->QueryInterface(riid, ppvObjOut); pUnk->Release(); RETURN_ON_FAILURE(hr); }
return hr; }
|