diff options
-rw-r--r-- | src/ToolBox/SOS/Strike/eeheap.cpp | 43 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/gcroot.cpp | 13 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/sos.cpp | 137 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/sos.h | 2 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/util.h | 10 | ||||
-rw-r--r-- | src/debug/daccess/daccess.cpp | 4 | ||||
-rw-r--r-- | src/debug/daccess/dacimpl.h | 6 | ||||
-rw-r--r-- | src/debug/daccess/request.cpp | 27 | ||||
-rw-r--r-- | src/inc/dacprivate.h | 20 | ||||
-rw-r--r-- | src/inc/sospriv.idl | 10 | ||||
-rw-r--r-- | src/pal/prebuilt/idl/sospriv_i.cpp | 4 | ||||
-rw-r--r-- | src/pal/prebuilt/inc/sospriv.h | 80 |
12 files changed, 303 insertions, 53 deletions
diff --git a/src/ToolBox/SOS/Strike/eeheap.cpp b/src/ToolBox/SOS/Strike/eeheap.cpp index 5a5680fcfb..c28c9641f5 100644 --- a/src/ToolBox/SOS/Strike/eeheap.cpp +++ b/src/ToolBox/SOS/Strike/eeheap.cpp @@ -868,8 +868,7 @@ DWORD GetNumComponents(TADDR obj) return Value; } -BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj, - DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers) +static MethodTableInfo* GetMethodTableInfo(DWORD_PTR dwAddrMethTable) { // Remove lower bits in case we are in mark phase dwAddrMethTable = dwAddrMethTable & ~3; @@ -880,12 +879,34 @@ BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj, // from the target DacpMethodTableData dmtd; // see code:ClrDataAccess::RequestMethodTableData for details - if (dmtd.Request(g_sos,dwAddrMethTable) != S_OK) - return FALSE; + if (dmtd.Request(g_sos, dwAddrMethTable) != S_OK) + return NULL; + info->BaseSize = dmtd.BaseSize; info->ComponentSize = dmtd.ComponentSize; info->bContainsPointers = dmtd.bContainsPointers; + + // The following request doesn't work on older runtimes. For those, the + // objects would just look like non-collectible, which is acceptable. + DacpMethodTableCollectibleData dmtcd; + if (SUCCEEDED(dmtcd.Request(g_sos, dwAddrMethTable))) + { + info->bCollectible = dmtcd.bCollectible; + info->LoaderAllocatorObjectHandle = TO_TADDR(dmtcd.LoaderAllocatorObjectHandle); + } + } + + return info; +} + +BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj, + DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers) +{ + MethodTableInfo* info = GetMethodTableInfo(dwAddrMethTable); + if (info == NULL) + { + return FALSE; } bContainsPointers = info->bContainsPointers; @@ -911,6 +932,20 @@ BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj, return TRUE; } +BOOL GetCollectibleDataEfficient(DWORD_PTR dwAddrMethTable, BOOL& bCollectible, TADDR& loaderAllocatorObjectHandle) +{ + MethodTableInfo* info = GetMethodTableInfo(dwAddrMethTable); + if (info == NULL) + { + return FALSE; + } + + bCollectible = info->bCollectible; + loaderAllocatorObjectHandle = info->LoaderAllocatorObjectHandle; + + return TRUE; +} + // This function expects stat to be valid, and ready to get statistics. void GatherOneHeapFinalization(DacpGcHeapDetails& heapDetails, HeapStat *stat, BOOL bAllReady, BOOL bShort) { diff --git a/src/ToolBox/SOS/Strike/gcroot.cpp b/src/ToolBox/SOS/Strike/gcroot.cpp index e4262208e4..cd13719094 100644 --- a/src/ToolBox/SOS/Strike/gcroot.cpp +++ b/src/ToolBox/SOS/Strike/gcroot.cpp @@ -1009,7 +1009,7 @@ GCRootImpl::RootNode *GCRootImpl::GetGCRefs(RootNode *path, RootNode *node) // Only calculate the size if we need it. size_t objSize = 0; - if (mSize || node->MTInfo->ContainsPointers) + if (mSize || node->MTInfo->ContainsPointers || node->MTInfo->Collectible) { objSize = GetSizeOfObject(obj, node->MTInfo); @@ -1027,7 +1027,7 @@ GCRootImpl::RootNode *GCRootImpl::GetGCRefs(RootNode *path, RootNode *node) } // Early out: If the object doesn't contain any pointers, return. - if (!node->MTInfo->ContainsPointers) + if (!node->MTInfo->ContainsPointers && !node->MTInfo->Collectible) return NULL; // Make sure we have the object's data in the cache. @@ -1139,6 +1139,15 @@ GCRootImpl::MTInfo *GCRootImpl::GetMTInfo(TADDR mt) curr->ComponentSize = (size_t)dmtd.ComponentSize; curr->ContainsPointers = dmtd.bContainsPointers ? true : false; + // The following request doesn't work on older runtimes. For those, the + // objects would just look like non-collectible, which is acceptable. + DacpMethodTableCollectibleData dmtcd; + if (SUCCEEDED(dmtcd.Request(g_sos, mt))) + { + curr->Collectible = dmtcd.bCollectible ? true : false; + curr->LoaderAllocatorObjectHandle = TO_TADDR(dmtcd.LoaderAllocatorObjectHandle); + } + // If this method table contains pointers, fill out and cache the GCDesc. if (curr->ContainsPointers) { diff --git a/src/ToolBox/SOS/Strike/sos.cpp b/src/ToolBox/SOS/Strike/sos.cpp index 64ee4b9a0c..5ff77a905a 100644 --- a/src/ToolBox/SOS/Strike/sos.cpp +++ b/src/ToolBox/SOS/Strike/sos.cpp @@ -180,6 +180,15 @@ namespace sos info->BaseSize = mMTData->BaseSize; info->ComponentSize = mMTData->ComponentSize; info->bContainsPointers = mMTData->bContainsPointers; + + // The following request doesn't work on older runtimes. For those, the + // objects would just look like non-collectible, which is acceptable. + DacpMethodTableCollectibleData mtcd; + if (SUCCEEDED(mtcd.Request(g_sos, GetMT()))) + { + info->bCollectible = mtcd.bCollectible; + info->LoaderAllocatorObjectHandle = TO_TADDR(mtcd.LoaderAllocatorObjectHandle); + } } if (mSize == (size_t)~0) @@ -380,14 +389,14 @@ namespace sos RefIterator::RefIterator(TADDR obj, LinearReadCache *cache) - : mCache(cache), mGCDesc(0), mArrayOfVC(false), mDone(false), mBuffer(0), mCurrSeries(0), + : mCache(cache), mGCDesc(0), mArrayOfVC(false), mDone(false), mBuffer(0), mCurrSeries(0), mLoaderAllocatorObjectHandle(0), i(0), mCount(0), mCurr(0), mStop(0), mObject(obj), mObjSize(0) { Init(); } RefIterator::RefIterator(TADDR obj, CGCDesc *desc, bool arrayOfVC, LinearReadCache *cache) - : mCache(cache), mGCDesc(desc), mArrayOfVC(arrayOfVC), mDone(false), mBuffer(0), mCurrSeries(0), + : mCache(cache), mGCDesc(desc), mArrayOfVC(arrayOfVC), mDone(false), mBuffer(0), mCurrSeries(0), mLoaderAllocatorObjectHandle(0), i(0), mCount(0), mCurr(0), mStop(0), mObject(obj), mObjSize(0) { Init(); @@ -403,6 +412,13 @@ namespace sos { if (mDone) Throw<Exception>("Attempt to move past the end of the iterator."); + + if (mCurr == mLoaderAllocatorObjectHandle) + { + // The mLoaderAllocatorObjectHandle is always the last reference returned + mDone = true; + return *this; + } if (!mArrayOfVC) { @@ -440,6 +456,14 @@ namespace sos mDone = true; } + if (mDone && mLoaderAllocatorObjectHandle != NULL) + { + // The iteration over all regular object references is done, but there is one more + // reference for collectible types - the LoaderAllocator for GC + mCurr = mLoaderAllocatorObjectHandle; + mDone = false; + } + return *this; } @@ -457,66 +481,89 @@ namespace sos { TADDR mt = ReadPointer(mObject); BOOL bContainsPointers = FALSE; - + BOOL bCollectible = FALSE; + TADDR loaderAllocatorObjectHandle; + if (!GetSizeEfficient(mObject, mt, FALSE, mObjSize, bContainsPointers)) Throw<DataRead>("Failed to get size of object."); - - if (!bContainsPointers) + + if (!GetCollectibleDataEfficient(mt, bCollectible, loaderAllocatorObjectHandle)) + Throw<DataRead>("Failed to get collectible info of object."); + + if (!bContainsPointers && !bCollectible) { mDone = true; return; } - - if (!mGCDesc) + + if (bContainsPointers) { - int entries = 0; - - if (FAILED(MOVE(entries, mt-sizeof(TADDR)))) - Throw<DataRead>("Failed to request number of entries."); - - // array of vc? - if (entries < 0) + if (!mGCDesc) { - entries = -entries; - mArrayOfVC = true; + int entries = 0; + + if (FAILED(MOVE(entries, mt-sizeof(TADDR)))) + Throw<DataRead>("Failed to request number of entries."); + + // array of vc? + if (entries < 0) + { + entries = -entries; + mArrayOfVC = true; + } + else + { + mArrayOfVC = false; + } + + size_t slots = 1 + entries * sizeof(CGCDescSeries)/sizeof(TADDR); + + ArrayHolder<TADDR> buffer = new TADDR[slots]; + + ULONG fetched = 0; + CLRDATA_ADDRESS address = TO_CDADDR(mt - slots*sizeof(TADDR)); + if (FAILED(g_ExtData->ReadVirtual(address, buffer, (ULONG)(slots*sizeof(TADDR)), &fetched))) + Throw<DataRead>("Failed to request GCDesc."); + + mBuffer = buffer.Detach(); + mGCDesc = (CGCDesc*)(mBuffer + slots); + } + + mCurrSeries = mGCDesc->GetHighestSeries(); + + if (!mArrayOfVC) + { + mCurr = mObject + mCurrSeries->GetSeriesOffset(); + mStop = mCurr + mCurrSeries->GetSeriesSize() + mObjSize; } else { - mArrayOfVC = false; + i = 0; + mCurr = mObject + mCurrSeries->startoffset; + mStop = mCurr + mCurrSeries->val_serie[i].nptrs * sizeof(TADDR); + mCount = (int)mGCDesc->GetNumSeries(); } - - size_t slots = 1 + entries * sizeof(CGCDescSeries)/sizeof(TADDR); - - ArrayHolder<TADDR> buffer = new TADDR[slots]; - - ULONG fetched = 0; - CLRDATA_ADDRESS address = TO_CDADDR(mt - slots*sizeof(TADDR)); - if (FAILED(g_ExtData->ReadVirtual(address, buffer, (ULONG)(slots*sizeof(TADDR)), &fetched))) - Throw<DataRead>("Failed to request GCDesc."); - - mBuffer = buffer.Detach(); - mGCDesc = (CGCDesc*)(mBuffer + slots); + + if (mCurr == mStop) + operator++(); + else if (mCurr >= mObject + mObjSize - plug_skew) + mDone = true; } - - mCurrSeries = mGCDesc->GetHighestSeries(); - - if (!mArrayOfVC) + else { - mCurr = mObject + mCurrSeries->GetSeriesOffset(); - mStop = mCurr + mCurrSeries->GetSeriesSize() + mObjSize; + mDone = true; } - else + + if (bCollectible) { - i = 0; - mCurr = mObject + mCurrSeries->startoffset; - mStop = mCurr + mCurrSeries->val_serie[i].nptrs * sizeof(TADDR); - mCount = (int)mGCDesc->GetNumSeries(); + mLoaderAllocatorObjectHandle = loaderAllocatorObjectHandle; + if (mDone) + { + // There are no object references, but there is still a reference for + // collectible types - the LoaderAllocator for GC + mCurr = mLoaderAllocatorObjectHandle; + } } - - if (mCurr == mStop) - operator++(); - else if (mCurr >= mObject + mObjSize - plug_skew) - mDone = true; } diff --git a/src/ToolBox/SOS/Strike/sos.h b/src/ToolBox/SOS/Strike/sos.h index 3778235964..ff5b53a9c7 100644 --- a/src/ToolBox/SOS/Strike/sos.h +++ b/src/ToolBox/SOS/Strike/sos.h @@ -501,6 +501,8 @@ namespace sos TADDR *mBuffer; CGCDescSeries *mCurrSeries; + TADDR mLoaderAllocatorObjectHandle; + int i, mCount; TADDR mCurr, mStop, mObject; diff --git a/src/ToolBox/SOS/Strike/util.h b/src/ToolBox/SOS/Strike/util.h index 78516546ac..ebad2e49ff 100644 --- a/src/ToolBox/SOS/Strike/util.h +++ b/src/ToolBox/SOS/Strike/util.h @@ -1660,9 +1660,11 @@ struct MethodTableInfo DWORD BaseSize; // Caching BaseSize and ComponentSize for a MethodTable DWORD ComponentSize; // here has HUGE perf benefits in heap traversals. BOOL bContainsPointers; + BOOL bCollectible; DWORD_PTR* GCInfoBuffer; // Start of memory of GC info CGCDesc* GCInfo; // Just past GC info (which is how it is stored) bool ArrayOfVC; + TADDR LoaderAllocatorObjectHandle; }; class MethodTableCache @@ -1680,9 +1682,11 @@ protected: info.BaseSize = 0; info.ComponentSize = 0; info.bContainsPointers = false; + info.bCollectible = false; info.GCInfo = NULL; info.ArrayOfVC = false; info.GCInfoBuffer = NULL; + info.LoaderAllocatorObjectHandle = NULL; } }; Node *head; @@ -1948,6 +1952,8 @@ size_t NextOSPageAddress (size_t addr); BOOL GetSizeEfficient(DWORD_PTR dwAddrCurrObj, DWORD_PTR dwAddrMethTable, BOOL bLarge, size_t& s, BOOL& bContainsPointers); +BOOL GetCollectibleDataEfficient(DWORD_PTR dwAddrMethTable, BOOL& bCollectible, TADDR& loaderAllocatorObjectHandle); + // ObjSize now uses the methodtable cache for its work too. size_t ObjectSize (DWORD_PTR obj, BOOL fIsLargeObject=FALSE); size_t ObjectSize(DWORD_PTR obj, DWORD_PTR mt, BOOL fIsValueClass, BOOL fIsLargeObject=FALSE); @@ -2856,8 +2862,10 @@ private: TADDR *Buffer; CGCDesc *GCDesc; + TADDR LoaderAllocatorObjectHandle; bool ArrayOfVC; bool ContainsPointers; + bool Collectible; size_t BaseSize; size_t ComponentSize; @@ -2874,7 +2882,7 @@ private: MTInfo() : MethodTable(0), TypeName(0), Buffer(0), GCDesc(0), - ArrayOfVC(false), ContainsPointers(false), BaseSize(0), ComponentSize(0) + ArrayOfVC(false), ContainsPointers(false), Collectible(false), BaseSize(0), ComponentSize(0) { } diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp index 1ce452bc2d..e7bef87c0c 100644 --- a/src/debug/daccess/daccess.cpp +++ b/src/debug/daccess/daccess.cpp @@ -3278,6 +3278,10 @@ ClrDataAccess::QueryInterface(THIS_ { ifaceRet = static_cast<ISOSDacInterface5*>(this); } + else if (IsEqualIID(interfaceId, __uuidof(ISOSDacInterface6))) + { + ifaceRet = static_cast<ISOSDacInterface6*>(this); + } else { *iface = NULL; diff --git a/src/debug/daccess/dacimpl.h b/src/debug/daccess/dacimpl.h index 6147de3dde..e05575c141 100644 --- a/src/debug/daccess/dacimpl.h +++ b/src/debug/daccess/dacimpl.h @@ -862,7 +862,8 @@ class ClrDataAccess public ISOSDacInterface2, public ISOSDacInterface3, public ISOSDacInterface4, - public ISOSDacInterface5 + public ISOSDacInterface5, + public ISOSDacInterface6 { public: ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget=0); @@ -1208,6 +1209,9 @@ public: // ISOSDacInterface5 virtual HRESULT STDMETHODCALLTYPE GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs); + // ISOSDacInterface6 + virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData(CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data); + // // ClrDataAccess. // diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp index 12864e7b0d..3a497b1a32 100644 --- a/src/debug/daccess/request.cpp +++ b/src/debug/daccess/request.cpp @@ -1955,6 +1955,33 @@ ClrDataAccess::GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTabl } HRESULT +ClrDataAccess::GetMethodTableCollectibleData(CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data) +{ + if (mt == 0 || data == NULL) + return E_INVALIDARG; + + SOSDacEnter(); + + MethodTable* pMT = PTR_MethodTable(TO_TADDR(mt)); + BOOL bIsFree = FALSE; + if (!pMT || !DacValidateMethodTable(pMT, bIsFree)) + { + hr = E_INVALIDARG; + } + else + { + data->bCollectible = pMT->Collectible(); + if (data->bCollectible) + { + data->LoaderAllocatorObjectHandle = pMT->GetLoaderAllocatorObjectHandle(); + } + } + + SOSDacLeave(); + return hr; +} + +HRESULT ClrDataAccess::GetMethodTableTransparencyData(CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *pTransparencyData) { if (mt == 0 || pTransparencyData == NULL) diff --git a/src/inc/dacprivate.h b/src/inc/dacprivate.h index 2f7482680d..47e79a131f 100644 --- a/src/inc/dacprivate.h +++ b/src/inc/dacprivate.h @@ -177,6 +177,25 @@ struct MSLAYOUT DacpMethodTableFieldData : ZeroInit<DacpMethodTableFieldData> } }; +struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit<DacpMethodTableCollectibleData> +{ + CLRDATA_ADDRESS LoaderAllocatorObjectHandle; + BOOL bCollectible; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + HRESULT hr; + ISOSDacInterface6 *pSOS6 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface6), (void**)&pSOS6))) + { + hr = pSOS6->GetMethodTableCollectibleData(addr, this); + pSOS6->Release(); + } + + return hr; + } +}; + struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit<DacpMethodTableTransparencyData> { BOOL bHasCriticalTransparentInfo; @@ -1043,5 +1062,6 @@ static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modif static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodTableCollectibleData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); #endif // _DACPRIVATE_H_ diff --git a/src/inc/sospriv.idl b/src/inc/sospriv.idl index 5b718210d7..589642675f 100644 --- a/src/inc/sospriv.idl +++ b/src/inc/sospriv.idl @@ -367,3 +367,13 @@ interface ISOSDacInterface5 : IUnknown { HRESULT GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs); }; + +[ + object, + local, + uuid(11206399-4B66-4EDB-98EA-85654E59AD45) +] +interface ISOSDacInterface6 : IUnknown +{ + HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); +}; diff --git a/src/pal/prebuilt/idl/sospriv_i.cpp b/src/pal/prebuilt/idl/sospriv_i.cpp index 7c0cd69bba..290b9b75d0 100644 --- a/src/pal/prebuilt/idl/sospriv_i.cpp +++ b/src/pal/prebuilt/idl/sospriv_i.cpp @@ -91,6 +91,10 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface4,0x74B9D34C,0xA612,0x4B07,0x93,0xDD,0 MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface5,0x127d6abe,0x6c86,0x4e48,0x8e,0x7b,0x22,0x07,0x81,0xc5,0x81,0x01); + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface6,0x11206399,0x4b66,0x4edb,0x98,0xea,0x85,0x65,0x4e,0x59,0xad,0x45); + + #undef MIDL_DEFINE_GUID #ifdef __cplusplus diff --git a/src/pal/prebuilt/inc/sospriv.h b/src/pal/prebuilt/inc/sospriv.h index 3b810cc9b6..8896720792 100644 --- a/src/pal/prebuilt/inc/sospriv.h +++ b/src/pal/prebuilt/inc/sospriv.h @@ -2272,6 +2272,86 @@ EXTERN_C const IID IID_ISOSDacInterface5; #endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */ + +#ifndef __ISOSDacInterface6_INTERFACE_DEFINED__ +#define __ISOSDacInterface6_INTERFACE_DEFINED__ + + /* interface ISOSDacInterface6 */ + /* [uuid][local][object] */ + + + EXTERN_C const IID IID_ISOSDacInterface6; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("11206399-4B66-4EDB-98EA-85654E59AD45") + ISOSDacInterface6 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData( + CLRDATA_ADDRESS mt, + struct DacpMethodTableCollectibleData *data) = 0; + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface6Vtbl + { + BEGIN_INTERFACE + + HRESULT(STDMETHODCALLTYPE *QueryInterface)( + ISOSDacInterface5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG(STDMETHODCALLTYPE *AddRef)( + ISOSDacInterface5 * This); + + ULONG(STDMETHODCALLTYPE *Release)( + ISOSDacInterface5 * This); + + HRESULT(STDMETHODCALLTYPE *GetMethodTableCollectibleData)( + CLRDATA_ADDRESS mt, + struct DacpMethodTableCollectibleData *data); + + END_INTERFACE + } ISOSDacInterface6Vtbl; + + interface ISOSDacInterface6 + { + CONST_VTBL struct ISOSDacInterface6Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface6_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface6_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \ + ( (This)->lpVtbl -> GetMethodTableCollectibleData(This,mt,data) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */ + /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ |