///////////////////////////////////////////////////////////////////// // client.cpp - demonstrates ATL_Inproc_Ex1 // // // // Jim Fawcett, CSE775 - Distributed Objects, Spring 2007 // ///////////////////////////////////////////////////////////////////// /* * Module Operations * ================= * Created as an empty Win32 Console Application, this module demonstrates * the minimum a client needs to do to activate and use an inproc COM * object. * * Required Files: * =============== * client.cpp, ATL_Inproc_Ex1.h * * Build Process: * ============== * - Build and register ATL_Inproc_Ex1 COM server * (registration is part of the build process with ATL) * - Build and run clien * * Maintenance History * =================== * 25 Feb 2007 * - first release */ #define _WIN32_WINNT 0x0601 #include #include "../ATLInprocEx1/ATLInprocEx1_i.h" #include void main() { std::wcout << L"\n Demonstrating use of ATL_Inproc_Ex1 "; std::wcout << L"\n =====================================\n"; HRESULT hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); if(!SUCCEEDED(hr)) { std::wcout << L"\n could not initialize COM"; } try { // COM wrapper objects should be embedded inside a scope // between calls to CoInitialize(Ex) and CoUninitialize // so that their destructors get called BEFORE the COM // libraries are shut down with CoUninitialize. // Doing this inside a try-catch block is a good way to // do that, because the wrappers will throw exceptions if // calls fail. // CComQIPtr pStrings; pStrings.CoCreateInstance(CLSID_Strings); if(pStrings != 0) { pStrings->PutString(L"Hi from client"); /////////////////////////////////////////////////////////////// // Using CComBSTR as an [out] parameter // - We don't need the call to Empty() here, because we // haven't used returnStr. However, if returnStr had some // contents we will get a memory leak unless we empty it // before the call. CComBSTR returnStr; std::wcout << L"\n\n Length of CComBSTR before [out] call: " << returnStr.Length(); returnStr.Empty(); pStrings->GetString(&returnStr); // note use of empty CComBSTR std::wcout << L"\n Length of CComBSTR after [out] call: " << returnStr.Length(); std::wcout << "\n " << returnStr.Detach(); /////////////////////////////////////////////////////////////// // Using a BSTR as an [out] parameter // - we're using an unnecessary allocation before call to // simulate what the CComBSTR is doing. // - you always want to supply an unallocated string that // proxy allocates and fills, and you use and deallocate. BSTR rStr = SysAllocString(L""); std::wcout << L"\n\n Length of BSTR before [out] call: " << SysStringLen(rStr); SysFreeString(rStr); pStrings->GetString(&rStr); // note use of unallocated BSTR std::wcout << L"\n Length of BSTR after [out] call: " << SysStringLen(rStr); std::wcout << "\n " << rStr; SysFreeString(rStr); } else { throw std::exception("CoCreateInstance failed"); } // Don't call release with pStrings. CComQIPtr destructor takes // care of that. } catch(std::exception& ex) { std::wcout << L"\n " << ex.what() << L"\n\n"; return; } std::wcout << L"\n\n"; CoUninitialize(); }