www.pudn.com > COM技术内幕配书源码.rar > CFACTORY.CPP
/////////////////////////////////////////////////////////// // // CFactory // - Base class for reusing a single class factory for // all components in a DLL // #include#include "Registry.h" #include "CFactory.h" /////////////////////////////////////////////////////////// // // Static variables // LONG CFactory::s_cServerLocks = 0 ; // Count of locks HMODULE CFactory::s_hModule = NULL ; // DLL module handle /////////////////////////////////////////////////////////// // // CFactory implementation // CFactory::CFactory(const CFactoryData* pFactoryData) : m_cRef(1) { m_pFactoryData = pFactoryData ; } // // IUnknown implementation // HRESULT __stdcall CFactory::QueryInterface(REFIID iid, void** ppv) { IUnknown* pI ; if ((iid == IID_IUnknown) || (iid == IID_IClassFactory)) { pI= this ; } else { *ppv = NULL ; return E_NOINTERFACE ; } pI->AddRef() ; *ppv = pI ; return S_OK ; } ULONG __stdcall CFactory::AddRef() { return ::InterlockedIncrement(&m_cRef) ; } ULONG __stdcall CFactory::Release() { if (::InterlockedDecrement(&m_cRef) == 0) { delete this ; return 0 ; } return m_cRef ; } // // IClassFactory implementation // HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) { // Aggregate only if the requested IID is IID_IUnknown. if ((pUnknownOuter != NULL) && (iid != IID_IUnknown)) { return CLASS_E_NOAGGREGATION ; } // Create the component. CUnknown* pNewComponent ; HRESULT hr = m_pFactoryData->CreateInstance(pUnknownOuter, &pNewComponent) ; if (FAILED(hr)) { return hr ; } // Initialize the component. hr = pNewComponent->Init() ; if (FAILED(hr)) { // Initialization failed. Release the component. pNewComponent->NondelegatingRelease() ; return hr ; } // Get the requested interface. hr = pNewComponent->NondelegatingQueryInterface(iid, ppv) ; // Release the reference held by the class factory. pNewComponent->NondelegatingRelease() ; return hr ; } // LockServer HRESULT __stdcall CFactory::LockServer(BOOL bLock) { if (bLock) { ::InterlockedIncrement(&s_cServerLocks) ; } else { ::InterlockedDecrement(&s_cServerLocks) ; } return S_OK ; } /////////////////////////////////////////////////////////// // // GetClassObject // - Create a class factory based on a CLSID. // HRESULT CFactory::GetClassObject(const CLSID& clsid, const IID& iid, void** ppv) { if ((iid != IID_IUnknown) && (iid != IID_IClassFactory)) { return E_NOINTERFACE ; } // Traverse the array of data looking for this class ID. for (int i = 0; i < g_cFactoryDataEntries; i++) { const CFactoryData* pData = &g_FactoryDataArray[i] ; if (pData->IsClassID(clsid)) { // Found the ClassID in the array of components we can // create. So create a class factory for this component. // Pass the CFactoryData structure to the class factory // so that it knows what kind of components to create. *ppv = (IUnknown*) new CFactory(pData) ; if (*ppv == NULL) { return E_OUTOFMEMORY ; } return NOERROR ; } } return CLASS_E_CLASSNOTAVAILABLE ; } // // Register all components. // HRESULT CFactory::RegisterAll() { for(int i = 0 ; i < g_cFactoryDataEntries ; i++) { RegisterServer(s_hModule, *(g_FactoryDataArray[i].m_pCLSID), g_FactoryDataArray[i].m_RegistryName, g_FactoryDataArray[i].m_szVerIndProgID, g_FactoryDataArray[i].m_szProgID) ; } return S_OK ; } HRESULT CFactory::UnregisterAll() { for(int i = 0 ; i < g_cFactoryDataEntries ; i++) { UnregisterServer(*(g_FactoryDataArray[i].m_pCLSID), g_FactoryDataArray[i].m_szVerIndProgID, g_FactoryDataArray[i].m_szProgID) ; } return S_OK ; } // // Determine if the component can be unloaded. // HRESULT CFactory::CanUnloadNow() { if (CUnknown::ActiveComponents() || IsLocked()) { return S_FALSE ; } else { return S_OK ; } } ////////////////////////////////////////////////////////// // // Exported functions // STDAPI DllCanUnloadNow() { return CFactory::CanUnloadNow() ; } // // Get class factory // STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) { return CFactory::GetClassObject(clsid, iid, ppv) ; } // // Server registration // STDAPI DllRegisterServer() { return CFactory::RegisterAll() ; } STDAPI DllUnregisterServer() { return CFactory::UnregisterAll() ; } /////////////////////////////////////////////////////////// // // DLL module information // BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { CFactory::s_hModule = hModule ; } return TRUE ; }