// // Cmpnt.cpp - Component // #include <objbase.h> #include <stdio.h> // sprintf #include <stdlib.h> //splitpath #include "Iface.h" #include "Util.h" #include "CUnknown.h" #include "CFactory.h" // Needed for module handle #include "Cmpnt.h" static inline void trace(char* msg) { Util::Trace("Component", msg, S_OK) ;} static inline void trace(char* msg, HRESULT hr) { Util::Trace("Component", msg, hr) ;} // // Type library name // const char szTypeLibName[] = "Server.tlb" ; /////////////////////////////////////////////////////////// // // Interface IX - Implementation // HRESULT __stdcall CA::Fx() { trace("!!!!! We made it here!!!!!") ; return S_OK ; } HRESULT __stdcall CA::FxStringIn(BSTR bstrIn) { // Display the incoming string. ostrstream sout ; sout << "FxStringIn received a string: " << bstrIn << ends ; trace(sout.str()) ; return S_OK ; } HRESULT __stdcall CA::FxStringOut(BSTR* pbstrOut) { const wchar_t wsz[] = L"[String from FxStringOut]" ; // Allocate an outgoing string. *pbstrOut = ::SysAllocString(wsz) ; if (*pbstrOut == NULL) { return E_OUTOFMEMORY ; } return S_OK ; } HRESULT __stdcall CA::FxFakeError() { trace("FxFakeError is faking an error.") ; // Create the error info object. ICreateErrorInfo* pICreateErr ; HRESULT hr = ::CreateErrorInfo(&pICreateErr) ; if (FAILED(hr)) { return E_FAIL ; } // pICreateErr->SetHelpFile(...) ; // pICreateErr->SetHelpContext(...) ; pICreateErr->SetSource(L"InsideCOM.Chap11") ; pICreateErr->SetDescription( L"This is a fake error generated by the component.") ; IErrorInfo* pIErrorInfo = NULL ; hr = pICreateErr->QueryInterface(IID_IErrorInfo, (void**)&pIErrorInfo) ; if (SUCCEEDED(hr)) { ::SetErrorInfo(0L, pIErrorInfo) ; pIErrorInfo->Release() ; } pICreateErr->Release() ; return E_FAIL ; } // // Constructor // CA::CA(IUnknown* pUnknownOuter) : CUnknown(pUnknownOuter), m_pITypeInfo(NULL) { // Empty } // // Destructor // CA::~CA() { if (m_pITypeInfo != NULL) { m_pITypeInfo->Release() ; } trace("Destroy self.") ; } // // NondelegatingQueryInterface implementation // HRESULT __stdcall CA::NondelegatingQueryInterface(const IID& iid, void** ppv) { if (iid == IID_IX) { return FinishQI(static_cast<IX*>(this), ppv) ; } else if (iid == IID_IDispatch) { trace("Queried for IDispatch.") ; return FinishQI(static_cast<IDispatch*>(this), ppv) ; } else if (iid == IID_ISupportErrorInfo) { trace("Queried for ISupportErrorInfo.") ; return FinishQI(static_cast<ISupportErrorInfo*>(this), ppv) ; } else { return CUnknown::NondelegatingQueryInterface(iid, ppv) ; } } // // Load and register the type library. // HRESULT CA::Init() { HRESULT hr ; // Load TypeInfo on demand if we haven't already loaded it. if (m_pITypeInfo == NULL) { ITypeLib* pITypeLib = NULL ; hr = ::LoadRegTypeLib(LIBID_ServerLib, 1, 0, // Major/Minor version numbers 0x00, &pITypeLib) ; if (FAILED(hr)) { trace("LoadRegTypeLib Failed, now trying LoadTypeLib.", hr) ; // If it wasn't registered, try to load it from the path. // Get the fullname of the server's executable. char szModule[512] ; DWORD dwResult = ::GetModuleFileName(CFactory::s_hModule, szModule, 512) ; // Split the fullname to get the pathname. char szDrive[_MAX_DRIVE]; char szDir[_MAX_DIR]; _splitpath(szModule, szDrive, szDir, NULL, NULL) ; // Append name of registry. char szTypeLibFullName[_MAX_PATH]; sprintf(szTypeLibFullName, "%s%s%s", szDrive, szDir, szTypeLibName) ; // convert to wide char wchar_t wszTypeLibFullName[_MAX_PATH] ; mbstowcs(wszTypeLibFullName, szTypeLibFullName, _MAX_PATH) ; // if LoadTypeLib succeeds, it will have registered // the type library for us. // for the next time. hr = ::LoadTypeLib(wszTypeLibFullName, &pITypeLib) ; if(FAILED(hr)) { trace("LoadTypeLib Failed.", hr) ; return hr; } // Ensure that the type library is registered. hr = RegisterTypeLib(pITypeLib, wszTypeLibFullName, NULL) ; if(FAILED(hr)) { trace("RegisterTypeLib Failed.", hr) ; return hr ; } } // Get type information for the interface of the object. hr = pITypeLib->GetTypeInfoOfGuid(IID_IX, &m_pITypeInfo) ; pITypeLib->Release() ; if (FAILED(hr)) { trace("GetTypeInfoOfGuid failed.", hr) ; return hr ; } } return S_OK ; } /////////////////////////////////////////////////////////// // // Creation function used by CFactory // HRESULT CA::CreateInstance(IUnknown* pUnknownOuter, CUnknown** ppNewComponent ) { if (pUnknownOuter != NULL) { // Don't allow aggregation (just for the heck of it). return CLASS_E_NOAGGREGATION ; } *ppNewComponent = new CA(pUnknownOuter) ; return S_OK ; } /////////////////////////////////////////////////////////// // // IDispatch implementation // HRESULT __stdcall CA::GetTypeInfoCount(UINT* pCountTypeInfo) { trace("GetTypeInfoCount call succeeded.") ; *pCountTypeInfo = 1 ; return S_OK ; } HRESULT __stdcall CA::GetTypeInfo( UINT iTypeInfo, LCID, // This object does not support localization. ITypeInfo** ppITypeInfo) { *ppITypeInfo = NULL ; if(iTypeInfo != 0) { trace("GetTypeInfo call failed -- bad iTypeInfo index.") ; return DISP_E_BADINDEX ; } trace("GetTypeInfo call succeeded.") ; // Call AddRef and return the pointer. m_pITypeInfo->AddRef() ; *ppITypeInfo = m_pITypeInfo ; return S_OK ; } HRESULT __stdcall CA::GetIDsOfNames( const IID& iid, OLECHAR** arrayNames, UINT countNames, LCID, // Localization is not supported. DISPID* arrayDispIDs) { if (iid != IID_NULL) { trace("GetIDsOfNames call failed -- bad IID.") ; return DISP_E_UNKNOWNINTERFACE ; } trace("GetIDsOfNames call succeeded.") ; HRESULT hr = m_pITypeInfo->GetIDsOfNames(arrayNames, countNames, arrayDispIDs) ; return hr ; } HRESULT __stdcall CA::Invoke( DISPID dispidMember, const IID& iid, LCID, // Localization is not supported. WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO* pExcepInfo, UINT* pArgErr) { if (iid != IID_NULL) { trace("Invoke call failed -- bad IID.") ; return DISP_E_UNKNOWNINTERFACE ; } ::SetErrorInfo(0, NULL) ; trace("Invoke call succeeded.") ; HRESULT hr = m_pITypeInfo->Invoke( static_cast<IDispatch*>(this), dispidMember, wFlags, pDispParams, pvarResult, pExcepInfo, pArgErr) ; return hr ; }