//+------------------------------------------------------------------- // // File: comclass.cpp // // Contents: Test DLL class code that can be used for both apt // model and single threaded application // // Classes: // // Functions: // // History: 03-Nov-94 Ricksa // //-------------------------------------------------------------------- #undef _UNICODE #undef UNICODE #include #include #include // Global count of ULONG g_UseCount = 0; //+------------------------------------------------------------------- // // Class: CBasicBndCF // // Synopsis: Class Factory for CBasicBnd // // Methods: IUnknown - QueryInterface, AddRef, Release // IClassFactory - CreateInstance // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- class FAR CBasicBndCF: public IClassFactory { public: // Constructor/Destructor CBasicBndCF(REFCLSID rclsid); ~CBasicBndCF(); // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IClassFactory STDMETHODIMP CreateInstance( IUnknown FAR* pUnkOuter, REFIID iidInterface, void FAR* FAR* ppv); STDMETHODIMP LockServer(BOOL fLock); private: ULONG _cRefs; REFCLSID _rclsid; DWORD _dwThreadId; }; //+------------------------------------------------------------------- // // Class: CBasicBnd // // Synopsis: Test class CBasicBnd // // Methods: // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- class FAR CBasicBnd: public IPersist { public: // Constructor/Destructor CBasicBnd(REFCLSID rclsd, DWORD dwThreadId); ~CBasicBnd(); // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IPersist - only thing we implement because it // gives us a nice way to figure who we are talking to. STDMETHODIMP GetClassID(LPCLSID lpClassID); private: ULONG _cRefs; REFCLSID _rclsid; DWORD _dwThreadId; }; extern "C" BOOL WINAPI DllMain( HANDLE, DWORD, LPVOID) { static BOOL fFirst = TRUE; if (fFirst) { InitDll(); fFirst = FALSE; } return TRUE; } //+------------------------------------------------------------------- // // Function: DllGetClassObject // // Synopsis: Called by client (from within BindToObject et al) // interface requested should be IUnknown or IClassFactory - // Creates ClassFactory object and returns pointer to it // // Arguments: REFCLSID clsid - class id // REFIID iid - interface id // void FAR* FAR* ppv- pointer to class factory interface // // Returns: TRUE // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv) { if (!IsEqualGUID(iid, IID_IUnknown) && !IsEqualGUID(iid, IID_IClassFactory)) { return E_NOINTERFACE; } if (IsEqualGUID(clsid, clsidServer)) { *ppv = new CBasicBndCF(clsidServer); return (*ppv != NULL) ? S_OK : E_OUTOFMEMORY; } return E_FAIL; } STDAPI DllCanUnloadNow(void) { return (g_UseCount == 0) ? S_OK : S_FALSE; } //+------------------------------------------------------------------- // // Member: CBasicBndCF::CBasicBndCF() // // Synopsis: The constructor for CBAsicBnd. // // Arguments: None // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- CBasicBndCF::CBasicBndCF(REFCLSID rclsid) : _cRefs(1), _rclsid(rclsid), _dwThreadId(GetCurrentThreadId()) { g_UseCount++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::~CBasicBndCF() // // Synopsis: The destructor for CBasicCF. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- CBasicBndCF::~CBasicBndCF() { g_UseCount--; return; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::QueryInterface // // Synopsis: Only IUnknown and IClassFactory supported // //-------------------------------------------------------------------- STDMETHODIMP CBasicBndCF::QueryInterface(REFIID iid, void FAR * FAR * ppv) { if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID(iid, IID_IClassFactory)) { *ppv = this; AddRef(); return S_OK; } else { *ppv = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) CBasicBndCF::AddRef(void) { return ++_cRefs; } STDMETHODIMP_(ULONG) CBasicBndCF::Release(void) { ULONG cRefs = --_cRefs; if (cRefs == 0) { delete this; } return cRefs; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::CreateInstance // // Synopsis: This is called by Binding process to create the // actual class object // //-------------------------------------------------------------------- STDMETHODIMP CBasicBndCF::CreateInstance( IUnknown FAR* pUnkOuter, REFIID iidInterface, void FAR* FAR* ppv) { if (GetCurrentThreadId() != _dwThreadId) { return E_UNEXPECTED; } HRESULT hresult = S_OK; if (pUnkOuter != NULL) { return CLASS_E_NOAGGREGATION; } CBasicBnd *pbb = new FAR CBasicBnd(_rclsid, _dwThreadId); if (pbb == NULL) { return E_OUTOFMEMORY; } hresult = pbb->QueryInterface(iidInterface, ppv); pbb->Release(); return hresult; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::LockServer // // Synopsis: Who knows what this is for? // //-------------------------------------------------------------------- STDMETHODIMP CBasicBndCF::LockServer(BOOL fLock) { if (GetCurrentThreadId() != _dwThreadId) { return E_UNEXPECTED; } if (fLock) { g_UseCount++; } else { g_UseCount--; } return S_OK; } //+------------------------------------------------------------------- // // Member: CBasicBnd::CBasicBnd() // // Synopsis: The constructor for CBAsicBnd. I // // Arguments: None // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- CBasicBnd::CBasicBnd(REFCLSID rclsid, DWORD dwThreadId) : _cRefs(1), _rclsid(rclsid), _dwThreadId(dwThreadId) { g_UseCount++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::~CBasicBndObj() // // Synopsis: The destructor for CBAsicBnd. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- CBasicBnd::~CBasicBnd() { g_UseCount--; return; } //+------------------------------------------------------------------- // // Member: CBasicBnd::QueryInterface // // Returns: S_OK // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- STDMETHODIMP CBasicBnd::QueryInterface(REFIID iid, void **ppv) { if (GetCurrentThreadId() != _dwThreadId) { return E_UNEXPECTED; } if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID(iid, IID_IPersist)) { *ppv = this; AddRef(); return S_OK; } else { *ppv = NULL; return E_NOINTERFACE; } } //+------------------------------------------------------------------- // // Member: CBasicBnd::AddRef // // Synopsis: Standard stuff // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBasicBnd::AddRef(void) { return _cRefs++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::Release // // Synopsis: Standard stuff // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBasicBnd::Release(void) { ULONG cRefs; if ((cRefs = --_cRefs) == 0) { delete this; } return cRefs; } //+------------------------------------------------------------------- // // Interface: IPersist // // Synopsis: IPersist interface methods // Need to return a valid class id here // // History: 21-Nov-92 SarahJ Created // STDMETHODIMP CBasicBnd::GetClassID(LPCLSID classid) { if (GetCurrentThreadId() != _dwThreadId) { return E_UNEXPECTED; } *classid = _rclsid; return S_OK; }