//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1999 ** //********************************************************************* // // CFACTORY.CPP - Implementation of IClassFactory // // HISTORY: // // 1/27/99 a-jaswed Created. // // Base class for reusing a single class factory for all // components in a DLL. #include #include "cfactory.h" #include "registry.h" /////////////////////////////////////////////////////////// // Static variables // LONG CFactory::s_cServerLocks = 0 ; // Count of locks HMODULE CFactory::s_hModule = NULL; // DLL Module Handle. #ifdef _OUTPROC_SERVER_ DWORD CFactory::s_dwThreadID = 0; #endif /////////////////////////////////////////////////////////// // CFactory implementation // CFactory::CFactory(const CFactoryData* pFactoryData) : m_cRef(1) { m_pFactoryData = pFactoryData; } /////////////////////////////////////////////////////////// // IUnknown implementation /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // QueryInterface // 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; } /////////////////////////////////////////////////////////// // AddRef // ULONG __stdcall CFactory::AddRef() { return ::InterlockedIncrement(&m_cRef); } /////////////////////////////////////////////////////////// // Release // ULONG __stdcall CFactory::Release() { if (::InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } /////////////////////////////////////////////////////////// // IClassFactory Implementation /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // CreateInstance // HRESULT __stdcall CFactory::CreateInstance( IUnknown* pOuterUnknown, const IID& iid, void** ppv) { // Aggregate only if the requested iid is IID_IUnknown if ((pOuterUnknown != NULL) && (iid != IID_IUnknown)) { return CLASS_E_NOAGGREGATION; } // Create the component. CUnknown* pNewComponent ; HRESULT hr = m_pFactoryData->CreateInstance(pOuterUnknown, &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); } // If this is an outproc server check to see if we should shut down. CloseExe() ; //@local return S_OK; } ////////////////////////////////////////////////////////// // GetClassObject - Creates a class factory based on 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; } ////////////////////////////////////////////////////////// // CanUnloadNow - Determine if component can be unloaded. // HRESULT CFactory::CanUnloadNow() { if (CUnknown::ActiveComponents() || IsLocked()) { return S_FALSE; } else { return S_OK; } } ////////////////////////////////////////////////////////// // CFactory Member Function ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // 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 ); // Perform any additional registration. if (g_FactoryDataArray[i].SpecialRegistration != NULL) { g_FactoryDataArray[i].SpecialRegistration(TRUE); } } return S_OK ; } ////////////////////////////////////////////////////////// // Unregister all components. // HRESULT CFactory::UnregisterAll() { for(int i = 0 ; i < g_cFactoryDataEntries ; i++) { // Undo any additional registration. if (g_FactoryDataArray[i].SpecialRegistration != NULL) { g_FactoryDataArray[i].SpecialRegistration(FALSE); } UnregisterServer(*(g_FactoryDataArray[i].m_pCLSID), g_FactoryDataArray[i].m_szVerIndProgID, g_FactoryDataArray[i].m_szProgID ); } return S_OK; } #ifndef _OUTPROC_SERVER_ ////////////////////////////////////////////////////////// // Exported functions ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // DllCanUnloadNow // 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(); } ////////////////////////////////////////////////////////// // Unregistration // 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) hModule; } return TRUE; } #else ////////////////////////////////////////////////////////// // Out of process Server support ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // Start factories // BOOL CFactory::StartFactories() { CFactoryData* pStart = &g_FactoryDataArray[0]; const CFactoryData* pEnd = &g_FactoryDataArray[g_cFactoryDataEntries-1]; for(CFactoryData* pData = pStart ; pData <= pEnd ; pData++) { // Initialize the class factory pointer and cookie. pData->m_pIClassFactory = NULL ; pData->m_dwRegister = NULL ; // Create the class factory for this component. IClassFactory* pIFactory = new CFactory(pData); // Register the class factory. DWORD dwRegister ; HRESULT hr = ::CoRegisterClassObject( *pData->m_pCLSID, (IUnknown*)pIFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, //REGCLS_MULTI_SEPARATE, //@Multi &dwRegister) ; if (FAILED(hr)) { pIFactory->Release() ; return FALSE ; } // Set the data. pData->m_pIClassFactory = pIFactory ; pData->m_dwRegister = dwRegister ; } return TRUE ; } ////////////////////////////////////////////////////////// // Stop factories // void CFactory::StopFactories() { CFactoryData* pStart = &g_FactoryDataArray[0]; const CFactoryData* pEnd = &g_FactoryDataArray[g_cFactoryDataEntries-1]; for(CFactoryData* pData = pStart ; pData <= pEnd ; pData++) { // Get the magic cookie and stop the factory from running. DWORD dwRegister = pData->m_dwRegister ; if (dwRegister != 0) { ::CoRevokeClassObject(dwRegister) ; } // Release the class factory. IClassFactory* pIFactory = pData->m_pIClassFactory; if (pIFactory != NULL) { pIFactory->Release() ; } } } #endif //_OUTPROC_SERVER_