315 lines
7.8 KiB
C++
315 lines
7.8 KiB
C++
|
// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
|
||
|
|
||
|
#include "header.h"
|
||
|
|
||
|
#include "ClassF.H"
|
||
|
#include "Unknown.H" // for CREATEFNOFOBJECT
|
||
|
#include "localobj.h"
|
||
|
#include "localsrv.h"
|
||
|
|
||
|
#ifndef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static const char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
HRESULT CreateOleObjectFromIndex(IUnknown *, int Index, void **, REFIID);
|
||
|
|
||
|
CClassFactory::CClassFactory(int iIndex)
|
||
|
{
|
||
|
m_iIndex = iIndex;
|
||
|
m_cRefs = 1;
|
||
|
}
|
||
|
|
||
|
CClassFactory::~CClassFactory ()
|
||
|
{
|
||
|
ASSERT_COMMENT(m_cRefs == 0, "Object being deleted with refs!");
|
||
|
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 {
|
||
|
*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
|
||
|
|
||
|
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
|
||
|
|
||
|
ULONG CClassFactory::Release(void)
|
||
|
{
|
||
|
ASSERT_COMMENT(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
|
||
|
//
|
||
|
// EnterCriticalSection(&g_CriticalSection);
|
||
|
if (!g_fCheckedForLicense) {
|
||
|
g_fMachineHasLicense = TRUE; // 17-Jun-1997 [ralphw] no license check
|
||
|
g_fCheckedForLicense = TRUE;
|
||
|
}
|
||
|
// LeaveCriticalSection(&g_CriticalSection);
|
||
|
|
||
|
// check to see if they have the appropriate license to create this stuff
|
||
|
//
|
||
|
// 08-Jan-1997 [ralphw] CLASS_E_NOTLICENSED disappeared from the header files
|
||
|
//
|
||
|
// 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
|
||
|
|
||
|
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
|
||
|
{
|
||
|
// update the lock count. crit sect these in case of another thread.
|
||
|
|
||
|
if (fLock)
|
||
|
InterlockedIncrement(&g_cLocks);
|
||
|
else {
|
||
|
ASSERT_COMMENT(g_cLocks, "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);
|
||
|
|
||
|
pLicInfo->cbLicInfo = sizeof(LICINFO);
|
||
|
|
||
|
// 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)
|
||
|
{
|
||
|
*pbstr = NULL;
|
||
|
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;
|
||
|
|
||
|
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
|
||
|
|
||
|
HRESULT CreateOleObjectFromIndex
|
||
|
(
|
||
|
IUnknown *pUnkOuter,
|
||
|
int iIndex,
|
||
|
void **ppvObjOut,
|
||
|
REFIID riid
|
||
|
)
|
||
|
{
|
||
|
ASSERT_COMMENT(CREATEFNOFOBJECT(iIndex), "All creatable objects must have creation fn!");
|
||
|
IUnknown* 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.
|
||
|
|
||
|
HRESULT hr;
|
||
|
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;
|
||
|
}
|