/////////////////////////////////////////////////////////////////////// // ConsoleClient.cpp - client for component MarshalInterfacePtr // // uses CComQIPtr and CComBSTR // // // // Platform: Dell Dimension 9150, Windows XP Pro, SP2 // // Application: Demonstrate Marshaling Interface Pointers // // CSE775 - Distributed Objects, Spring 2006 // // Modified: Jim Fawcett, Syracuse Univ, CST 2-187 // // (315) 443-3948, jfawcett@twcny.rr.com // /////////////////////////////////////////////////////////////////////// #include "..\\MarshalInterfacePtr\\stdafx.h" #include #include #include #include #include "..\\MarshalInterfacePtr\\MarshalInterfacePtr.h" #include "..\\threads\\threads.h" using namespace std; class proc : public processing { public: proc(IStream* pStream, DWORD thrdID) : _pStream(pStream), mainThreadID_(thrdID) {} processing* clone() { return new proc(_pStream, mainThreadID_); } void run() { // create second STA CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // unmarshal interface pointer IMarshalIFPtr* pIMarsh = 0; HRESULT hr = CoGetInterfaceAndReleaseStream( (IStream*)_pStream, IID_IMarshalIFPtr, (LPVOID*)&pIMarsh ); if(!SUCCEEDED(hr)) throw "unmarshaling interface pointer failed"; std::cout << "\n retrieved marshaled pointer in child thread"; // and use it std::cout << "\n sending message from secondary STA to component"; CComBSTR bstr("Hi from client's secondary STA"); hr = pIMarsh->putString(bstr); if(!SUCCEEDED(hr)) throw "call to putString(BSTR) failed"; CoUninitialize(); std::cout << "\n child thread terminating"; PostThreadMessage(mainThreadID_, WM_QUIT, 0, 0); } private: IStream* _pStream; DWORD mainThreadID_; }; // int main(int argc, char* argv[]) { cout << "\n Testing Marshaling of Interface Pointers " << "\n ==========================================\n" << endl; // create first STA CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); try { CComQIPtr pIMarsh; pIMarsh.CoCreateInstance(CLSID_MarshalIFPtr); // note: Used as instance, not as smart pointer, e.g.: dot notation if(pIMarsh) { // demonstrate component CComBSTR bstr = "hi from client's primary STA"; HRESULT hr; hr = pIMarsh->putString(bstr); if(!SUCCEEDED(hr)) throw "call to putString(BSTR) failed"; bstr.Empty(); hr = pIMarsh->getString(&bstr); if(!SUCCEEDED(hr)) throw "call to getString(BSTR*) failed"; wcout << "\n In primary STA, client received: \"" << (wchar_t*)bstr << "\"\n"; // marshal interface pointer to stream IStream* pStream ; hr = CoMarshalInterThreadInterfaceInStream( IID_IMarshalIFPtr, pIMarsh, &pStream ); // create child thread that will receive marshaled interface pointer proc tproc(pStream, GetCurrentThreadId()); thread t(tproc); t.start(); // start pumping messages so apartments can communicate MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { DispatchMessage(&msg); } std::cout << "\n message loop stopped"; } // else { throw "could not create IMarshalInterfacePtr instance"; } } catch(const char* msg) { cout << "\n " << msg << "\n\n"; } // Uninitialize COM Library // Note: If you declare CComQIPtr in the same scope as CoInitialize // and CoUninitialize(), then you must call pIString.Release() before // calling CoUninitialize(). If declared in a nested scope, as here, // the destructor, ~CComQIPtr() will call release for you, when it // leaves the inner scope. CoUninitialize() ; cout << "\n\n"; return 0 ; }