#pragma once // Extensions to ATL to enable things it doesn't natively support template class MarsIProvideClassInfo2Impl : public IProvideClassInfo2Impl { }; template class MarsIDispatchImpl : public IDispatchImpl { public: STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr) { HRESULT hr = IDispatchImpl::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); hr = SanitizeResult(hr); if (DISP_E_EXCEPTION == hr) { // We're getting DISP_E_EXCEPTION returns which are not generated by Mars // whenever invalid parameter types are passed. They're probably coming // from oleaut itself. // ASSERT(NULL != m_pwszException); if ((NULL != m_pwszException) && (NULL != pexcepinfo)) { memset(pexcepinfo, 0, sizeof(EXCEPINFO)); pexcepinfo->wCode = (WORD)dispidMember; pexcepinfo->bstrSource = SysAllocString(L"OM Exception"); pexcepinfo->bstrDescription = SysAllocString(m_pwszException); } } return hr; } protected: LPWSTR m_pwszException; }; // each module implements this themselves HRESULT GetMarsTypeLib(ITypeLib **ppTypeLib); //================================================================== // Begin CComTypeInfoHolder override // // By providing our own CComTypeInfoHolder, we can load the type // library ourselves, rather than requiring it to be loaded from // the registry as ATL does. Only "GetTI" is changed from // ATL source. Since GetTI isn't virtual we need to duplicate // the entire class. // CMarsTypeInfoHolder accepts an ITypeLib * (with reference) // instead of a LIBID in m_plibid // //================================================================== // ATL doesn't support multiple LCID's at the same time // Whatever LCID is queried for first is the one that is used. class CMarsTypeInfoHolder { // Should be 'protected' but can cause compiler to generate fat code. public: const GUID* m_pguid; const GUID* m_plibid; WORD m_wMajor; WORD m_wMinor; ITypeInfo* m_pInfo; long m_dwRef; struct stringdispid { CComBSTR bstr; int nLen; DISPID id; }; stringdispid* m_pMap; int m_nCount; public: HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) { HRESULT hr = S_OK; if (m_pInfo == NULL) hr = GetTI(lcid); *ppInfo = m_pInfo; if (m_pInfo != NULL) { m_pInfo->AddRef(); hr = S_OK; } return hr; } HRESULT GetTI(LCID lcid); HRESULT EnsureTI(LCID lcid) { HRESULT hr = S_OK; if (m_pInfo == NULL) hr = GetTI(lcid); return hr; } // This function is called by the module on exit // It is registered through _Module.AddTermFunc() static void __stdcall Cleanup2(DWORD_PTR dw) { CMarsTypeInfoHolder* p = (CMarsTypeInfoHolder*) dw; if (p->m_pInfo != NULL) p->m_pInfo->Release(); p->m_pInfo = NULL; delete [] p->m_pMap; p->m_pMap = NULL; } HRESULT GetTypeInfo(UINT /* itinfo */, LCID lcid, ITypeInfo** pptinfo) { HRESULT hRes = E_POINTER; if (pptinfo != NULL) hRes = GetTI(lcid, pptinfo); return hRes; } HRESULT GetIDsOfNames(REFIID /* riid */, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) { HRESULT hRes = EnsureTI(lcid); if (m_pInfo != NULL) { for (int i=0; i<(int)cNames; i++) { int n = ocslen(rgszNames[i]); for (int j=m_nCount-1; j>=0; j--) { if ((n == m_pMap[j].nLen) && (memcmp(m_pMap[j].bstr, rgszNames[i], m_pMap[j].nLen * sizeof(OLECHAR)) == 0)) { rgdispid[i] = m_pMap[j].id; break; } // Give debug warning if we differ only in case //DEBUG_ONLY(StrEql(m_pMap[j].bstr, rgszNames[i])); } if (j < 0) { // Not a warning. Common for behaviors as Trident passes all calls to // our IDispatch for the first shot. We should possibly just return // failure in this case instead of delegating to oleaut. hRes = m_pInfo->GetIDsOfNames(rgszNames + i, 1, &rgdispid[i]); if (FAILED(hRes)) break; } } } return hRes; } HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { HRESULT hRes = EnsureTI(lcid); if (m_pInfo != NULL) hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); return hRes; } HRESULT LoadNameCache(ITypeInfo* pTypeInfo) { TYPEATTR* pta; HRESULT hr = pTypeInfo->GetTypeAttr(&pta); if (SUCCEEDED(hr)) { m_nCount = pta->cFuncs; m_pMap = m_nCount == 0 ? 0 : new stringdispid[m_nCount]; for (int i=0; iGetFuncDesc(i, &pfd))) { CComBSTR bstrName; if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL))) { m_pMap[i].bstr.Attach(bstrName.Detach()); m_pMap[i].nLen = SysStringLen(m_pMap[i].bstr); m_pMap[i].id = pfd->memid; } pTypeInfo->ReleaseFuncDesc(pfd); } } pTypeInfo->ReleaseTypeAttr(pta); } return S_OK; } }; inline HRESULT CMarsTypeInfoHolder::GetTI(LCID lcid) { UNREFERENCED_PARAMETER(lcid); // Change: removed asserts if (m_pInfo != NULL) return S_OK; HRESULT hRes = E_FAIL; EnterCriticalSection(&_Module.m_csTypeInfoHolder); if (m_pInfo == NULL) { ITypeLib* pTypeLib; // Here's a change // hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); hRes = GetMarsTypeLib(&pTypeLib); // End change if (SUCCEEDED(hRes)) { CComPtr spTypeInfo; hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo); if (SUCCEEDED(hRes)) { CComPtr spInfo(spTypeInfo); CComPtr spTypeInfo2; if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2))) spInfo = spTypeInfo2; LoadNameCache(spInfo); m_pInfo = spInfo.Detach(); } pTypeLib->Release(); } } LeaveCriticalSection(&_Module.m_csTypeInfoHolder); _Module.AddTermFunc(Cleanup2, (DWORD_PTR)this); return hRes; } //================================================================== // End CComTypeInfoHolder override //================================================================== // CComClassPtr is like CComPtr but it works with C++ classes, by not // assuming that we can cast to IUnknown unambiguously. // Use caution when initializing within your constructor. You can't // AddRef an object which hasn't finished constructing yet, so you can // only initialize smart pointers to object which don't contain you. template class _NoAddRefReleaseOnCComClassPtr : public T { public: // If you get a compile error here, make sure that the destructors // for any CComClassPtr<> classes are protected instead of private ~_NoAddRefReleaseOnCComClassPtr() {} private: STDMETHOD_(ULONG, AddRef)()=0; STDMETHOD_(ULONG, Release)()=0; }; template class CComClassPtr { public: typedef T _PtrClass; CComClassPtr() { p=NULL; } CComClassPtr(T* lp) { if ((p = lp) != NULL) p->AddRef(); } CComClassPtr(const CComClassPtr& lp) { if ((p = lp.p) != NULL) p->AddRef(); } ~CComClassPtr() { if (p) p->Release(); } void Release() { T* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } operator T*() const { return p; } T& operator*() const { ATLASSERT(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really //what is needed, however, take the address of the p member explicitly. T** operator&() { ATLASSERT(p==NULL); return &p; } HRESULT PassivateAndRelease() { if (p) { HRESULT hr = p->Passivate(); Release(); return hr; } return S_FALSE; } _NoAddRefReleaseOnCComClassPtr* operator->() const { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComClassPtr*)p; } T* AtlComClassPtrAssign(T** pp, T* lp) { if (lp != NULL) lp->AddRef(); if (*pp) (*pp)->Release(); *pp = lp; return lp; } T* operator=(T* lp) { return AtlComClassPtrAssign(&p, lp); } T* operator=(const CComClassPtr& lp) { return AtlComClassPtrAssign(&p, lp.p); } bool operator!() const { return (p == NULL); } bool operator<(T* pT) const { return p < pT; } bool operator==(T* pT) const { return p == pT; } // Compare two objects for equivalence bool IsEqualObject(T* pOther) { return (p == pOther); } void Attach(T* p2) { if (p) p->Release(); p = p2; } T* Detach() { T* pt = p; p = NULL; return pt; } HRESULT CopyTo(T** ppT) { ATLASSERT(ppT != NULL); if (ppT == NULL) return E_POINTER; *ppT = p; if (p) p->AddRef(); return S_OK; } template HRESULT QueryInterface(Q** pp) const { ATLASSERT(pp != NULL && *pp == NULL); return p->QueryInterface(__uuidof(Q), (void**)pp); } T* p; }; ////////////////////////////////////////////////////////////////////////////// // CMarsComDispatchDriver / Specialization of CComQIPtr // // This is better than CComDispatchDriver for these reasons: // - CComDispatchDriver in atl30 doesn't define an assignment/copy constructor // - CcomDispatchDriver doesn't use _NoAddRefReleaseOnCComPtr // - Added "const" to methods which are const // class CMarsComDispatchDriver { public: CMarsComDispatchDriver() { p = NULL; } CMarsComDispatchDriver(IDispatch* lp) { if ((p = lp) != NULL) p->AddRef(); } CMarsComDispatchDriver(IUnknown* lp) { p=NULL; if (lp != NULL) lp->QueryInterface(IID_IDispatch, (void **)&p); } CMarsComDispatchDriver(const CMarsComDispatchDriver& lp) { if ((p = lp.p) != NULL) p->AddRef(); } ~CMarsComDispatchDriver() { if (p) p->Release(); } void Release() {if (p) p->Release(); p=NULL;} operator IDispatch*() const {return p;} IDispatch& operator*() const {ATLASSERT(p!=NULL); return *p; } IDispatch** operator&() {ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr* operator->() const { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr*)p; } //IDispatch* operator->() {ATLASSERT(p!=NULL); return p; } IDispatch* operator=(IDispatch* lp){return (IDispatch*)AtlComPtrAssign((IUnknown**)&p, lp);} IDispatch* operator=(IUnknown* lp) { return (IDispatch*)AtlComQIPtrAssign((IUnknown**)&p, lp, IID_IDispatch); } IDispatch* operator=(const CMarsComDispatchDriver& lp) { return (IDispatch*)AtlComPtrAssign((IUnknown**)&p, lp.p); } BOOL operator!() const {return (p == NULL) ? TRUE : FALSE;} HRESULT GetPropertyByName(LPCOLESTR lpsz, VARIANT* pVar) { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = GetProperty(p, dwDispID, pVar); return hr; } HRESULT GetProperty(DISPID dwDispID, VARIANT* pVar) { ATLASSERT(p); return GetProperty(p, dwDispID, pVar); } HRESULT PutPropertyByName(LPCOLESTR lpsz, VARIANT* pVar) { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = PutProperty(p, dwDispID, pVar); return hr; } HRESULT PutProperty(DISPID dwDispID, VARIANT* pVar) { ATLASSERT(p); return PutProperty(p, dwDispID, pVar); } HRESULT GetIDOfName(LPCOLESTR lpsz, DISPID* pdispid) { return p->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpsz, 1, LOCALE_USER_DEFAULT, pdispid); } // Invoke a method by DISPID with no parameters HRESULT Invoke0(DISPID dispid, VARIANT* pvarRet = NULL) { DISPPARAMS dispparams = { NULL, NULL, 0, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with no parameters HRESULT Invoke0(LPCOLESTR lpszName, VARIANT* pvarRet = NULL) { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke0(dispid, pvarRet); return hr; } // Invoke a method by DISPID with a single parameter HRESULT Invoke1(DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) { DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with a single parameter HRESULT Invoke1(LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke1(dispid, pvarParam1, pvarRet); return hr; } // Invoke a method by DISPID with two parameters HRESULT Invoke2(DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) { CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with two parameters HRESULT Invoke2(LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); return hr; } // Invoke a method by DISPID with N parameters HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) { DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with Nparameters HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = InvokeN(dispid, pvarParams, nParams, pvarRet); return hr; } static HRESULT GetProperty(IDispatch* pDisp, DISPID dwDispID, VARIANT* pVar) { ATLTRACE2(atlTraceCOM, 0, _T("CPropertyHelper::GetProperty\n")); DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; return pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, pVar, NULL, NULL); } static HRESULT PutProperty(IDispatch* pDisp, DISPID dwDispID, VARIANT* pVar) { ATLTRACE2(atlTraceCOM, 0, _T("CPropertyHelper::PutProperty\n")); DISPPARAMS dispparams = {NULL, NULL, 1, 1}; dispparams.rgvarg = pVar; DISPID dispidPut = DISPID_PROPERTYPUT; dispparams.rgdispidNamedArgs = &dispidPut; if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) { HRESULT hr = pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &dispparams, NULL, NULL, NULL); if (SUCCEEDED(hr)) return hr; } return pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); } IDispatch* p; }; #define CComDispatchDriver _DONT_USE_CComDispatchDriver_USE_CMarsComDispatchDriver ////////////////////////////////////////////////////////////////////////////// // CMarsSimpleArray / Specialization of CSimpleArray // // This is better than CSimpleArray for these reasons: // overloaded the operator=() and defined a copy constructor. // Fixed various pointer math to use + instead of & because the operator&() // on contained smart types (like CComPtr) gets called accidentally if you // do this: &m_aT[i] instead of (m_aT + i). // ///////////////////////////////////////////////////////////////////////////// // Collection helpers - CMarsSimpleArray #ifdef new #pragma push_macro("new") #define _ATL_REDEF_NEW #undef new #endif template class CMarsSimpleArray { public: T* m_aT; int m_nSize; int m_nAllocSize; // Construction/destruction CMarsSimpleArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0) { } ~CMarsSimpleArray() { RemoveAll(); } CMarsSimpleArray(const CMarsSimpleArray ¤t) : m_aT(NULL), m_nSize(0), m_nAllocSize(0) { *this = current; } CMarsSimpleArray &operator=(const CMarsSimpleArray &right) { if (&right != this) { // BUGBUG (tnoonan) -- this code is going to potentially leak // if the new size is smaller than the old. T *aT = NULL; aT = (T *)realloc(m_aT, right.m_nAllocSize * sizeof(T)); // Did the realloc succeed? if (aT) { m_aT = aT; m_nSize = right.m_nSize; m_nAllocSize = right.m_nAllocSize; // WARNING: This is not a simple mempcy() for a very specific reason! // Each element must be copied with = in case the T class has an // overloaded operator=(). (i.e. in the case of smart ptrs). // for (int idx = 0; idx < m_nSize; ++idx) { m_aT[idx] = right.m_aT[idx]; } } } return *this; } // Operations int GetSize() const { return m_nSize; } BOOL Add(T& t) { if(m_nSize == m_nAllocSize) { T* aT; int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2); aT = (T*)realloc(m_aT, nNewAllocSize * sizeof(T)); if(aT == NULL) return FALSE; m_nAllocSize = nNewAllocSize; m_aT = aT; } m_nSize++; SetAtIndex(m_nSize - 1, t); return TRUE; } BOOL Remove(T& t) { int nIndex = Find(t); if(nIndex == -1) return FALSE; return RemoveAt(nIndex); } BOOL RemoveAt(int nIndex) { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); m_aT[nIndex].~T(); if(nIndex != (m_nSize - 1)) { // // BUGFIX: Use m_aT + nIndex instead of &m_aT[nIndex] to avoid calling type's operator &() // memmove((void*)(m_aT + nIndex), (void*)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T)); ZeroMemory((void*)(m_aT + (m_nSize-1)), sizeof(m_aT[0])); } m_nSize--; return TRUE; } BOOL InsertAt(int nIndex, T& t) { // Index equal to size means to insert at the end ATLASSERT(nIndex >= 0 && nIndex <= m_nSize); // First check if we have room... if(m_nSize == m_nAllocSize) { T* aT; int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2); aT = (T*)realloc(m_aT, nNewAllocSize * sizeof(T)); if(aT == NULL) return FALSE; m_nAllocSize = nNewAllocSize; m_aT = aT; } // If we're not adding to the end, then we need to shift elements past the insertion point // down one. if (nIndex < m_nSize) { memmove( (void*)(m_aT + (nIndex + 1)), (void*)(m_aT + (nIndex)), sizeof(T) * (m_nSize - nIndex)); // TRICKY: This memmove is a HACK -- it doesn't call the ctors and dtors of the elements. // However below, we're going to make an assignment, and that assignment is going to // cause the operator=() to fire on user types, which might mess up any // internal pointers. Ouch. We need to avoid that by wiping out the memory // destructively first. // // The reason this is bad is because the memmove has caused the nIndex and nIndex + 1 // entries to both share the same data, including pointers, so we have danglers. :-( // ZeroMemory((void*)(m_aT + nIndex), sizeof(T)); } m_nSize++; SetAtIndex(nIndex, t); return TRUE; } void RemoveAll() { if(m_aT != NULL) { for(int i = 0; i < m_nSize; i++) m_aT[i].~T(); free(m_aT); m_aT = NULL; } m_nSize = 0; m_nAllocSize = 0; } T& operator[] (int nIndex) const { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); return m_aT[nIndex]; } T* GetData() const { return m_aT; } // Implementation class Wrapper { public: Wrapper(T& _t) : t(_t) { } template void *operator new(size_t, _Ty* p) { return p; } T t; }; void SetAtIndex(int nIndex, T& t) { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); // // BUGFIX: Use m_aT + nIndex instead of &m_aT[nIndex] to avoid calling type's operator &() // new(m_aT + nIndex) Wrapper(t); } int Find(T& t) const { for(int i = 0; i < m_nSize; i++) { if(m_aT[i] == t) return i; } return -1; // not found } }; // CMarsSimpleArray // for arrays of simple types template class CMarsSimpleValArray : public CMarsSimpleArray< T > { public: BOOL Add(T t) { return CMarsSimpleArray< T >::Add(t); } BOOL Remove(T t) { return CMarsSimpleArray< T >::Remove(t); } T operator[] (int nIndex) const { return CMarsSimpleArray< T >::operator[](nIndex); } CMarsSimpleValArray &operator=(const CMarsSimpleValArray &right) { if (&right != this) { T *aT = NULL; aT = (T *)realloc(m_aT, right.m_nAllocSize * sizeof(T)); // Did the realloc succeed? if (aT) { m_aT = aT; m_nSize = right.m_nSize; m_nAllocSize = right.m_nAllocSize; CopyMemory(m_aT, right.m_aT, sizeof(T) * m_nSize); } } return *this; } }; #ifdef _ATL_REDEF_NEW #pragma pop_macro("new") #undef _ATL_REDEF_NEW #endif //-=-=-=-=-=-=-=-=-=-=-=-=-=-= // class CComTableMarshalPtr //-=-=-=-=-=-=-=-=-=-=-=-=-=-= template class CComTableMarshalPtr : public CComPtr { public: CComTableMarshalPtr(DWORD dwGITKey); virtual ~CComTableMarshalPtr(); static HRESULT RegisterInterface(IUnknown *pUnk, DWORD *pdwKey); static HRESULT RevokeInterface(DWORD dwKey); private: CComTableMarshalPtr(); // Protect access to default ctor }; // CComTableMarshalPtr //============================================================================ // class CComTableMarshalPtr //============================================================================ template CComTableMarshalPtr::CComTableMarshalPtr(DWORD dwKey) { CComPtr spGIT(CMarsGlobalsManager::GIT()); if (spGIT) { I *pInt = NULL; HRESULT hr = spGIT->GetInterfaceFromGlobal(dwKey, __uuidof(I), (void **)&pInt); if (SUCCEEDED(hr)) Attach(pInt); } } // CComTableMarshalPtr template CComTableMarshalPtr::~CComTableMarshalPtr() { } // ~CComTableMarshalPtr //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= template HRESULT CComTableMarshalPtr::RegisterInterface(IUnknown *pInt, DWORD *pdwKey) { HRESULT hr = E_INVALIDARG; if (IsValidInterfacePtr(pInt) && IsValidWritePtr(pdwKey)) { CComPtr spGIT(CMarsGlobalsManager::GIT()); ATLASSERT(spGIT); if (spGIT) { hr = spGIT->RegisterInterfaceInGlobal(pInt, __uuidof(I), pdwKey); } } return hr; } // RegisterInterface //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // CComTableMarshalPtr::RevokeInterface() // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= template HRESULT CComTableMarshalPtr::RevokeInterface(DWORD dwKey) { HRESULT hr = E_FAIL; CComPtr spGIT(CMarsGlobalsManager::GIT()); ATLASSERT(spGIT); if (spGIT) { hr = spGIT->RevokeInterfaceFromGlobal(dwKey); } return hr; } // RevokeInterface typedef CComEnum > CComVariantEnum; ////////////////////////////////////////////////////////////////////////////// // CMarsComEnumVariant - Simple derivation for convenience. This is the standard // type of a CComEnum for use in a collection that returns IEnumVARIANT. // // Our helper class has some luxury features that completely handle the common // case of take a CMarsSimpleArray full of "stuff," stuffing those things into // an array of CComVariant's (so we can be type-agnostic about what the // "things" are), and then creates a CComEnum and puts it in an out-param. // template class CMarsComEnumVariant : public CComEnum > { public: static HRESULT CreateFromMarsSimpleArray(CMarsSimpleArray > &arr, IUnknown **ppUnk) { // Internal API, so rip if the out param is bad ATLASSERT(NULL != ppUnk); HRESULT hr = E_FAIL; // Create one of ourselves... CComObject > > > *pEnum = NULL; hr = CComObject > > >::CreateInstance(&pEnum); if (SUCCEEDED(hr)) { // Allocation must have succeeded if no error HRESULT ATLASSERT(pEnum); pEnum->AddRef(); VARIANT *rgVar = new VARIANT[arr.GetSize()]; LONG idxEntry; if (rgVar) { HRESULT hrTestForDispatch = E_FAIL; for (idxEntry = 0; idxEntry < arr.GetSize(); idxEntry++) { CComClassPtr spElt; spElt = arr.operator[](idxEntry); hrTestForDispatch = spElt->QueryInterface(IID_IDispatch, (void **)&V_DISPATCH(&rgVar[idxEntry])); // // This had better succeed: the type I must be a dispatch interface, because otherwise, // you can't pass this object to script anyway, so what's the point of the collection??? // If you really want an IEnumXXXX for your non-automation interfaces, use ATL's CComEnum // directly with appropriate template parameters. // ATLASSERT(SUCCEEDED(hrTestForDispatch)); V_VT(&rgVar[idxEntry]) = VT_DISPATCH; } // If this succeeds, then ATL will have taken care of freeing our array for // us. How nice of it. // hr = pEnum->Init(&rgVar[0], &rgVar[arr.GetSize()], NULL, AtlFlagTakeOwnership); if (SUCCEEDED(hr)) { hr = pEnum->QueryInterface(IID_IUnknown, (void **)ppUnk); } else { for(idxEntry = 0; idxEntry < arr.GetSize(); idxEntry++) { VariantClear(&rgVar[idxEntry]); } delete[] rgVar; } } else { hr = E_OUTOFMEMORY; } pEnum->Release(); } // If CreateInstance SUCCEEDED return hr; } };