/////////////////////////////////////////////////////////////////////// // client.cpp - Client that uses the connectable object protocol // // to react to events in the component. // // // // Eddon & Eddon, Inside Distributed COM, authors: // // Jim Fawcett, CSE791 - Distributed Objects, Cosmetic Modifications // /////////////////////////////////////////////////////////////////////// #define _WIN32_DCOM #include #include #include #include "Component\component.h" using namespace std; /////////////////////////////////////////////////////////////////////// // sink component class CSink : public IOutGoing { public: // IUnknown ULONG __stdcall AddRef(); ULONG __stdcall Release(); HRESULT __stdcall QueryInterface(REFIID iid, void** ppv); // IOutGoing HRESULT __stdcall GotMessage(int Message); CSink() : m_cRef(0) { } ~CSink() { } private: long m_cRef; }; ULONG CSink::AddRef() { return ++m_cRef; } ULONG CSink::Release() { if(--m_cRef != 0) return m_cRef; delete this; return 0; } // HRESULT CSink::QueryInterface(REFIID riid, void** ppv) { if(riid == IID_IUnknown) { *ppv = (IUnknown*)this; } else if(riid == IID_IOutGoing) { cout << "Component: CInsideDCOM::QueryInterface() for IOutGoing" << endl; *ppv = (IOutGoing*)this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } HRESULT CSink::GotMessage(int Message) { if(Message == (int)'b' || Message == (int)'B') PlaySound("BrockschmidtQuack", NULL, SND_RESOURCE|SND_ASYNC); cout << "CSink::GotMessage is " << (char)Message << endl; return S_OK; } // /////////////////////////////////////////////////////////////////////// // entry to client code void main() { cout << "Client: Calling CoInitialize()" << endl; CoInitializeEx(NULL, COINIT_MULTITHREADED); IUnknown* pUnknown; cout << "Client: Calling CoCreateInstance() " << endl; CoCreateInstance( CLSID_InsideDCOM,NULL,CLSCTX_LOCAL_SERVER,IID_IUnknown,(void**)&pUnknown ); IConnectionPointContainer* pConnectionPointContainer; HRESULT hr = pUnknown-> QueryInterface( IID_IConnectionPointContainer, (void**)&pConnectionPointContainer ); if(FAILED(hr)) { cout << "Not a connectable object, going to exit now" << endl; return; } IEnumConnectionPoints* pEnumConnectionPoints; IEnumConnectionPoints* pEnumConnectionPoints2; hr = pConnectionPointContainer-> EnumConnectionPoints(&pEnumConnectionPoints); // Note: // Clone(...) method allows client to create a copy of an enumerator // to look at other members of collection, but return easily to the // current member, simply by using the original enumerator. Clone is // demonstrated here, but is not doing anything useful. ULONG num_fetched; IConnectionPoint* pConnectionPoint; hr = pEnumConnectionPoints->Clone(&pEnumConnectionPoints2); hr = pEnumConnectionPoints2->Next(1, &pConnectionPoint, &num_fetched); cout << "Next hr = " << hr << " num_fetched = " << num_fetched << endl; pEnumConnectionPoints->Release(); pEnumConnectionPoints2->Release(); IID my_iid; pConnectionPoint->GetConnectionInterface(&my_iid); char buffer[39]; OLECHAR ppsz[39]; StringFromGUID2(my_iid, ppsz, 39); WideCharToMultiByte(CP_ACP, 0, ppsz, 39, buffer, 39, NULL, NULL); cout << "IID: " << buffer << endl; // IConnectionPointContainer* CPC; pConnectionPoint->GetConnectionPointContainer(&CPC); if(CPC == pConnectionPointContainer) cout << " THEY ARE EQUAL " << endl; CPC->Release(); ///////////////////////////////////////////////////////////////////////////// // If there were more than one sink interface we can do the following: // // IConnectionPoint* pConnectionPoint; // hr = pConnectionPointContainer // ->FindConnectionPoint(IID_IOutGoing, &pConnectionPoint); // cout << "FindConnectionPoint returns " << hr << " pConnectionPoint = " // << pConnectionPoint << endl; CSink* mySink = new CSink; DWORD dwCookie; pConnectionPoint->Advise((IUnknown*)mySink, &dwCookie); cout << "CLIENT CALLED ADVISE" << hr << endl; IEnumConnections* pEnumConnections; pConnectionPoint->EnumConnections(&pEnumConnections); CONNECTDATA my_cd; ULONG dd; pEnumConnections->Next(1, &my_cd, &dd); cout << "MY COOKIE = " << my_cd.dwCookie << endl; cout << "MY COOKIE2 = " << dwCookie << endl; pEnumConnections->Release(); cout << "\n Will respond to events in component until you" << "\n Press any key to exit" << "\n component server will then shut down" << endl; _getch(); pConnectionPoint->Unadvise(dwCookie); pConnectionPoint->Release(); pConnectionPointContainer->Release(); cout << "Client: Calling Release() for pUnknown" << endl; hr = pUnknown->Release(); cout << "Client: Calling CoUninitialize()" << endl; CoUninitialize(); }