//=--------------------------------------------------------------------------= // 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; }