DEFCLSF.C
/******************************************************************************\ 
*       This is a part of the Microsoft Source Code Samples.  
*       Copyright 1995 - 1998 Microsoft Corporation. 
*       All rights reserved.  
*       This source code is only intended as a supplement to  
*       Microsoft Development Tools and/or WinHelp documentation. 
*       See these sources for detailed information regarding the  
*       Microsoft samples programs. 
\******************************************************************************/ 
 
// 
// This file contains the implementation of SHCreateDefClassObject 
// 
 
#include "priv.h" 
 
//========================================================================= 
// CDefClassFactory class 
//========================================================================= 
 
STDMETHODIMP CDefClassFactory_QueryInterface(IClassFactory FAR * pcf, REFIID riid, LPVOID FAR* ppvObj); 
ULONG STDMETHODCALLTYPE CDefClassFactory_AddRef(IClassFactory FAR * pcf); 
ULONG STDMETHODCALLTYPE CDefClassFactory_Release(IClassFactory FAR * pcf); 
STDMETHODIMP CDefClassFactory_CreateInstance(IClassFactory FAR * pcf, LPUNKNOWN pUnkOuter, 
                              REFIID riid, 
                              LPVOID FAR* ppvObject); 
STDMETHODIMP CDefClassFactory_LockServer(IClassFactory FAR * pcf, BOOL fLock); 
 
// 
// CDefClassFactory: Class definition 
// 
#pragma data_seg(".text") 
IClassFactoryVtbl c_vtblAppUIClassFactory = { 
            CDefClassFactory_QueryInterface, 
            CDefClassFactory_AddRef, 
            CDefClassFactory_Release, 
            CDefClassFactory_CreateInstance, 
    CDefClassFactory_LockServer 
}; 
#pragma data_seg() 
 
typedef struct 
{ 
    IClassFactory      cf; 
    UINT               cRef;// Reference count 
    LPFNCREATEINSTANCE lpfnCI;// CreateInstance callback entry 
    UINT FAR *         pcRefDll;// Reference count of the DLL 
    const IID FAR *    riidInst;// Optional interface for instance 
} CDefClassFactory; 
 
// 
// CDefClassFactory::QueryInterface 
// 
STDMETHODIMP CDefClassFactory_QueryInterface(IClassFactory FAR * pcf, REFIID riid, LPVOID FAR* ppvObj) 
{ 
    register CDefClassFactory * this=IToClassN(CDefClassFactory, cf, pcf); 
    if (IsEqualIID(riid, &IID_IClassFactory) 
     || IsEqualIID(riid, &IID_IUnknown)) 
    { 
(LPCLASSFACTORY)*ppvObj = &this->cf; 
this->cRef++; 
        return NOERROR; 
    } 
    return ResultFromScode(E_NOINTERFACE); 
} 
 
// 
// CDefClassFactory::AddRef 
// 
ULONG STDMETHODCALLTYPE CDefClassFactory_AddRef(IClassFactory FAR * pcf) 
{ 
    register CDefClassFactory * this=IToClassN(CDefClassFactory, cf, pcf); 
    return (++this->cRef); 
} 
 
// 
// CDefClassFactory::Release 
// 
ULONG STDMETHODCALLTYPE CDefClassFactory_Release(IClassFactory FAR * pcf) 
{ 
    register CDefClassFactory * this=IToClassN(CDefClassFactory, cf, pcf); 
    if (--this->cRef > 0) 
return this->cRef; 
 
    if (this->pcRefDll) { 
(*this->pcRefDll)--; 
    } 
    LocalFree((HLOCAL)this); 
 
    return 0; 
} 
 
// 
// CDefClassFactory::CDefClassFactory 
// 
STDMETHODIMP CDefClassFactory_CreateInstance(IClassFactory FAR * pcf, LPUNKNOWN pUnkOuter, 
                              REFIID riid, 
                              LPVOID FAR* ppvObject) 
{ 
    register CDefClassFactory * this=IToClassN(CDefClassFactory, cf, pcf); 
 
    // 
    // We don't support aggregation at all. 
    // 
    if (pUnkOuter) 
    { 
return ResultFromScode(CLASS_E_NOAGGREGATION); 
    } 
 
    // 
    // if this->riidInst is specified, they should match. 
    // 
    if (this->riidInst==NULL 
     || IsEqualIID(riid, this->riidInst) 
     || IsEqualIID(riid, &IID_IUnknown)) 
    { 
return this->lpfnCI(pUnkOuter, riid, ppvObject); 
    } 
 
    return ResultFromScode(E_NOINTERFACE); 
} 
 
// 
// CDefClassFactory::LockServer 
// 
STDMETHODIMP CDefClassFactory_LockServer(IClassFactory FAR * pcf, BOOL fLock) 
{ 
    // REVIEW: Is this appropriate? 
    return ResultFromScode(E_NOTIMPL); 
} 
 
 
// 
// CDefClassFactory constructor 
// 
CDefClassFactory * NEAR PASCAL CDefClassFactory_Create( 
    LPFNCREATEINSTANCE lpfnCI, UINT FAR * pcRefDll, REFIID riidInst) 
{ 
    register CDefClassFactory * pacf; 
    pacf = (CDefClassFactory *)LocalAlloc(LPTR, sizeof(CDefClassFactory)); 
    if (pacf) 
    { 
pacf->cf.lpVtbl = &c_vtblAppUIClassFactory; 
pacf->cRef++;  // pacf->cRef=0; (generates smaller code) 
pacf->pcRefDll = pcRefDll; 
pacf->lpfnCI = lpfnCI; 
pacf->riidInst = riidInst; 
if (pcRefDll) { 
    (*pcRefDll)++; 
} 
    } 
    return pacf; 
} 
 
 
// BUGBUG: remove this for build 86 
 
STDAPI Shell_CreateDefClassObject(REFIID riid, LPVOID FAR* ppv, 
 LPFNCREATEINSTANCE lpfnCI, UINT FAR * pcRefDll, 
 REFIID riidInst) 
{ 
    MessageBeep(0); 
    // DebugMsg(DM_TRACE, "Shell_CreateDefClassObject: obsolete, use SHCreateDefClassObject"); 
    return SHCreateDefClassObject(riid, ppv, lpfnCI, pcRefDll, riidInst); 
} 
 
// 
// creates a simple default implementation of IClassFactory 
// 
// Parameters: 
//  riid     -- Specifies the interface to the class object 
//  ppv      -- Specifies the pointer to LPVOID where the class object pointer 
//               will be returned. 
//  lpfnCI   -- Specifies the callback entry for instanciation. 
//  pcRefDll -- Specifies the address to the DLL reference count (optional) 
//  riidInst -- Specifies the interface to the instance (optional). 
// 
// Notes: 
//   The riidInst will be specified only if the instance of the class 
//  support only one interface. 
// 
STDAPI SHCreateDefClassObject(REFIID riid, LPVOID FAR* ppv, 
 LPFNCREATEINSTANCE lpfnCI, UINT FAR * pcRefDll, 
 REFIID riidInst) 
{ 
    // The default class factory supports only IClassFactory interface 
    if (IsEqualIID(riid, &IID_IClassFactory)) 
    { 
CDefClassFactory * pacf = CDefClassFactory_Create(lpfnCI, pcRefDll, riidInst); 
if (pacf) 
{ 
    (IClassFactory FAR *)*ppv = &pacf->cf; 
    return NOERROR; 
} 
return ResultFromScode(E_OUTOFMEMORY); 
    } 
    return ResultFromScode(E_NOINTERFACE); 
}