//+------------------------------------------------------------------- // // File: olebt.cpp // // Contents: Test DLL class code that be used multithreaded. // // Classes: // // Functions: // // History: 03-Nov-94 Ricksa // //-------------------------------------------------------------------- #undef _UNICODE #undef UNICODE #include #include #include // Global count of ULONG g_UseCount = 0; void PrintDebugMsg(char *pszMsg, DWORD dwData) { char wszBuf[256]; wsprintf(wszBuf, "olebt.dll: %s %d\n", pszMsg, dwData); OutputDebugString(wszBuf); } //+------------------------------------------------------------------- // // 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(void); ~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; IUnknown * _punkFm; }; //+------------------------------------------------------------------- // // Class: CBasicBnd // // Synopsis: Test class CBasicBnd // // Methods: // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- class FAR CBasicBnd: public IPersist { public: // Constructor/Destructor CBasicBnd(void); ~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; IUnknown * _punkFm; }; extern "C" BOOL WINAPI DllMain( HANDLE, DWORD, LPVOID) { 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) { *ppv = NULL; if (!IsEqualGUID(iid, IID_IUnknown) && !IsEqualGUID(iid, IID_IClassFactory) && !IsEqualGUID(iid, IID_IMarshal)) { return E_NOINTERFACE; } if (IsEqualGUID(clsid, clsidBothThreadedDll)) { IUnknown *punk = new CBasicBndCF(); HRESULT hr = punk->QueryInterface(iid, ppv); punk->Release(); return hr; } 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 Ricksa Created // //-------------------------------------------------------------------- CBasicBndCF::CBasicBndCF(void) : _cRefs(1), _punkFm(NULL) { PrintDebugMsg("Creating Class Factory", (DWORD) this); g_UseCount++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::~CBasicBndCF() // // Synopsis: The destructor for CBasicCF. // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- CBasicBndCF::~CBasicBndCF() { PrintDebugMsg("Deleting Class Factory", (DWORD) this); g_UseCount--; if (_punkFm != NULL) { _punkFm->Release(); } return; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::QueryInterface // // Synopsis: Only IUnknown and IClassFactory supported // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP CBasicBndCF::QueryInterface(REFIID iid, void **ppv) { HRESULT hr = E_NOINTERFACE; *ppv = NULL; if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID(iid, IID_IClassFactory)) { *ppv = this; AddRef(); hr = S_OK; } else if (IsEqualGUID(iid, IID_IMarshal)) { if (NULL == _punkFm) { hr = CoCreateFreeThreadedMarshaler(this, &_punkFm); } if (_punkFm != NULL) { return _punkFm->QueryInterface(iid, ppv); } } return hr; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::AddRef // // Synopsis: Increment reference count // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBasicBndCF::AddRef(void) { return ++_cRefs; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::Release // // Synopsis: Decrement reference count // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- 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) { HRESULT hresult = S_OK; if (pUnkOuter != NULL) { return CLASS_E_NOAGGREGATION; } CBasicBnd *pbb = new FAR CBasicBnd(); if (pbb == NULL) { return E_OUTOFMEMORY; } hresult = pbb->QueryInterface(iidInterface, ppv); pbb->Release(); return hresult; } //+------------------------------------------------------------------- // // Method: CBasicBndCF::LockServer // // Synopsis: Inc/Dec stay alive count // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP CBasicBndCF::LockServer(BOOL fLock) { if (fLock) { g_UseCount++; } else { g_UseCount--; } return S_OK; } //+------------------------------------------------------------------- // // Member: CBasicBnd::CBasicBnd() // // Synopsis: The constructor for CBAsicBnd. I // // Arguments: None // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- CBasicBnd::CBasicBnd(void) : _cRefs(1), _punkFm(NULL) { PrintDebugMsg("Creating App Object", (DWORD) this); g_UseCount++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::~CBasicBndObj() // // Synopsis: The destructor for CBAsicBnd. // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- CBasicBnd::~CBasicBnd(void) { PrintDebugMsg("Deleting App Object", (DWORD) this); g_UseCount--; return; } //+------------------------------------------------------------------- // // Member: CBasicBnd::QueryInterface // // Returns: S_OK // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP CBasicBnd::QueryInterface(REFIID iid, void **ppv) { if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID(iid, IID_IPersist)) { *ppv = this; AddRef(); return S_OK; } else if (IsEqualGUID(iid, IID_IMarshal)) { HRESULT hr; if (NULL == _punkFm) { hr = CoCreateFreeThreadedMarshaler(this, &_punkFm); } if (_punkFm != NULL) { hr = _punkFm->QueryInterface(iid, ppv); } return hr; } else { *ppv = NULL; return E_NOINTERFACE; } } //+------------------------------------------------------------------- // // Member: CBasicBnd::AddRef // // Synopsis: Standard stuff // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBasicBnd::AddRef(void) { return _cRefs++; } //+------------------------------------------------------------------- // // Member: CBasicBnd::Release // // Synopsis: Standard stuff // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBasicBnd::Release(void) { ULONG cRefs; if ((cRefs = --_cRefs) == 0) { delete this; } return cRefs; } //+------------------------------------------------------------------- // // Member: CBasicBnd::GetClassID // // Synopsis: Return the class id // // History: 03-Nov-94 Ricksa Created // //-------------------------------------------------------------------- STDMETHODIMP CBasicBnd::GetClassID(LPCLSID classid) { *classid = clsidBothThreadedDll; return S_OK; }