/////////////////////////////////////////////////////////////// // cmpnt.cpp - inproc_Ex1 component implements IHTML // // // // Language: C++, COM/IDL // // Platform: Dell Dimension 8100, Win2000, SP2 // // Application: Demonstration for CSE791 - Distrib. Objs // // Author: Jim Fawcett, Syracuse Univ, CST 2-187 // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// #include #include #include // COM library #include "Registry.h" // Registry helper functions #include "cmpnt_h.h" // Interface declarations generated // by MIDL from IDL using namespace std; /////////////////////////////////////////////////////////// // Note: // cmpnt.h will not exist until you run MIDL on cmpnt.idl // so you have to do that first, before compiling this // component. // /////////////////////////////////////////////////////////// // // Global variables // static HMODULE g_hModule = NULL ; // DLL module handle static long g_cComponents = 0 ; // Count of active components static long g_cServerLocks = 0 ; // Count of locks // Friendly name of component const char g_szFriendlyName[] = "CSE791 - inproc1_Ex1" ; // Version-independent ProgID const char g_szVerIndProgID[] = "inproc1_Ex1" ; // ProgID const char g_szProgID[] = "inproc1_Ex1" ; const wstring prefix = L" Component: \t\t"; // /////////////////////////////////////////////////////////// // // Component // class CA : public IHTML { public: virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ; virtual HRESULT __stdcall Fx(/*[in]*/ BSTR bstr); virtual HRESULT __stdcall Fy(/*[out]*/ BSTR *pBstr); CA() ; ~CA() ; private: long m_cRef ; // Reference count }; //----< Constructor >------------------------------------------ CA::CA() : m_cRef(1) { wcout << prefix + L"component construction"; wcout.flush(); cout << ", CA::ref count = " << m_cRef << endl; InterlockedIncrement(&g_cComponents) ; } //----< Destructor >------------------------------------------- CA::~CA() { InterlockedDecrement(&g_cComponents) ; wcout << prefix + L"component destruction"; wcout.flush(); cout << ", CA::ref count = " << m_cRef << endl; } // /////////////////////////////////////////////////////////////// // // IUnknown implementation // HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv) { wcout << prefix + L"QueryInterface" << endl; if (iid == IID_IUnknown) { *ppv = static_cast(this) ; } else if (iid == IID_IHTML) { *ppv = static_cast(this) ; wcout << prefix + L"return pointer to IHTML" << endl; } else { *ppv = NULL ; return E_NOINTERFACE ; } reinterpret_cast(*ppv)->AddRef() ; wcout << prefix + L"CA::QueryInterface"; wcout.flush(); cout << ", CA::ref count = " << m_cRef << endl; return S_OK ; } ULONG __stdcall CA::AddRef() { wcout << prefix + L"CA::AddRef(), CA::ref count = " << (m_cRef + 1) << endl; return InterlockedIncrement(&m_cRef) ; } ULONG __stdcall CA::Release() { wcout << prefix + L"CA::Release(), CA::ref count = " << (m_cRef - 1) << endl; if (InterlockedDecrement(&m_cRef) == 0) { delete this ; return 0 ; } return m_cRef ; } /////////////////////////////////////////////////////////////// // component method implementation // HRESULT __stdcall CA::Fx(BSTR bstr) { wcout << prefix + L" " << bstr << endl; return S_OK; } HRESULT __stdcall CA::Fy(BSTR *pBstr) { wcout << prefix + L"Allocating memory for BSTR" << endl; *pBstr = SysAllocString(OLESTR("message from component")); return S_OK; } // /////////////////////////////////////////////////////////// // // Class factory // class CFactory : public IClassFactory { public: // IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ; // IClassFactory virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) ; virtual HRESULT __stdcall LockServer(BOOL bLock) ; CFactory() : m_cRef(1) {} ~CFactory() { wcout << prefix + L"class factory destruction" << endl; } private: long m_cRef ; } ; /////////////////////////////////////////////////////////////// // Class factory IUnknown implementation // HRESULT __stdcall CFactory::QueryInterface(const IID& iid, void** ppv) { if ((iid == IID_IUnknown) || (iid == IID_IClassFactory)) { *ppv = static_cast(this) ; } else { *ppv = NULL ; return E_NOINTERFACE ; } reinterpret_cast(*ppv)->AddRef() ; wcout << prefix + L"CFactory::QueryInterface"; wcout.flush(); cout << ", CFactory::ref count = " << m_cRef << endl; return S_OK ; } // ULONG __stdcall CFactory::AddRef() { wcout << prefix + L"CFactory::AddRef(), CFactory::ref count = " << (m_cRef + 1) << endl; return InterlockedIncrement(&m_cRef) ; } ULONG __stdcall CFactory::Release() { wcout << prefix + L"CFactory::Release(), CFactory::ref count = " << (m_cRef - 1) << endl; 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) { wcout << prefix + L"create component in class factory" << endl; // Cannot aggregate. if (pUnknownOuter != NULL) { return CLASS_E_NOAGGREGATION ; } // Create component. CA* pA = new CA ; if (pA == NULL) { return E_OUTOFMEMORY ; } // Get the requested interface. HRESULT hr = pA->QueryInterface(iid, ppv) ; // Release the IUnknown pointer. // (If QueryInterface failed, component will delete itself.) pA->Release() ; return hr ; } // //----< LockServer >------------------------------------------- HRESULT __stdcall CFactory::LockServer(BOOL bLock) { if (bLock) { InterlockedIncrement(&g_cServerLocks) ; } else { InterlockedDecrement(&g_cServerLocks) ; } return S_OK ; } // /////////////////////////////////////////////////////////////// // // Exported functions // //----< Can DLL unload now? >---------------------------------- STDAPI DllCanUnloadNow() { wcout << prefix + L"DllCanUnloadNow()" << endl; if ((g_cComponents == 0) && (g_cServerLocks == 0)) { return S_OK ; } else { return S_FALSE ; } } //----< Get class factory >------------------------------------ STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) { wcout << prefix + L"DllGetClassObject creating class factory" << endl; // Can we create this component? if (clsid != CLSID_inproc1_Ex1) { return CLASS_E_CLASSNOTAVAILABLE ; } // Create class factory. CFactory* pFactory = new CFactory ; // No AddRef in constructor if (pFactory == NULL) { return E_OUTOFMEMORY ; } // Get requested interface. HRESULT hr = pFactory->QueryInterface(iid, ppv) ; pFactory->Release() ; return hr ; } // //----< Server registration >---------------------------------- STDAPI DllRegisterServer() { return RegisterServer(g_hModule, CLSID_inproc1_Ex1, g_szFriendlyName, g_szVerIndProgID, g_szProgID) ; } //----< Server unregistration >-------------------------------- STDAPI DllUnregisterServer() { return UnregisterServer( CLSID_inproc1_Ex1, g_szVerIndProgID, g_szProgID ) ; } //----< save DLL module information >-------------------------- BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { g_hModule = (HINSTANCE)hModule ; } return TRUE ; }