typedef HRESULT CALLBACK FNDumpFnCallBack(LPVOID pParam, LPCVOID pvKey, LPCVOID pvRef, LPCVOID pvAddress); template class StlDbgBase : public T { public: static HRESULT HrInitialRead(ULONG64 lpAddress, StlDbgBase** lpHeader); // Implement these in your derived classes: static HRESULT HrDumpAllFromUl64(ULONG64 lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); }; ////////////////////////////////////////////////////////////////////////////// //// STL MAP // ////////////////////////////////////////////////////////////////////////////// template class StlDbgMap : public StlDbgBase { private: typedef T::_Imp::_Node _StlDbgNode; typedef T::_Imp::_Nodeptr _StlDbgNodePtr; static HRESULT HrDumpAll(LPVOID lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); static HRESULT HrDumpNode(LPVOID pvHead, LPVOID pvDbgHead, DWORD dwLevel, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); public: static HRESULT HrDumpAllFromUl64(ULONG64 lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); }; ////////////////////////////////////////////////////////////////////////////// //// STL LIST // ////////////////////////////////////////////////////////////////////////////// template class StlDbgList : public StlDbgBase { private: typedef T::_Node _StlDbgNode; typedef T::_Nodeptr _StlDbgNodePtr; static HRESULT HrDumpAll(LPVOID lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); static HRESULT HrDumpNode(LPVOID pvHead, LPVOID pvDbgHead, DWORD dwLevel, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); public: static HRESULT HrDumpAllFromUl64(ULONG64 lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack); }; template HRESULT StlDbgMap::HrDumpNode(LPVOID pvHead, LPVOID pvDbgHead, DWORD dwLevel, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack) { _StlDbgNodePtr pHead = reinterpret_cast<_StlDbgNodePtr>(pvHead); _StlDbgNodePtr pDbgHead = reinterpret_cast<_StlDbgNodePtr>(pvDbgHead); dprintfVerbose("Dumping node (level %d) from head: [0x%08x]\n", dwLevel, pvDbgHead); if (!pvDbgHead) { return S_FALSE; } if ( (!pHead->_Left) && (!pHead->_Right) ) // aparently with the STL version we are using, this identifies an end node. { return S_FALSE; } HRESULT hr; hr = pFNDumpFnCallBack(lpParam, &(pHead->_Value.first), &(pHead->_Value.second), &(pDbgHead->_Value)); dprintfVerbose("%d: left is : 0x%08x\n", dwLevel, pHead->_Left); dprintfVerbose("%d: right is: 0x%08x\n", dwLevel, pHead->_Right); if (0 != pHead->_Left) { _StlDbgNodePtr pNodeLeft = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pNodeLeft) { ZeroMemory(pNodeLeft, sizeof(_StlDbgNodePtr)); dprintfVerbose("%d: Reading left child node ", dwLevel); hr = HrReadMemory(pHead->_Left, sizeof(_StlDbgNode), pNodeLeft); if (SUCCEEDED(hr)) { hr = HrDumpNode(pNodeLeft, pHead->_Left, dwLevel+1, lpParam, pFNDumpFnCallBack); } delete [] reinterpret_cast(pNodeLeft); } } if (0 != pHead->_Right) { _StlDbgNodePtr pNodeRight = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pNodeRight) { ZeroMemory(pNodeRight, sizeof(_StlDbgNode)); dprintfVerbose("%d: Reading right child node ", dwLevel); hr = HrReadMemory(pHead->_Right, sizeof(_StlDbgNode), pNodeRight); if (SUCCEEDED(hr)) { hr = HrDumpNode(pNodeRight, pHead->_Right, dwLevel+1, lpParam, pFNDumpFnCallBack); } delete [] reinterpret_cast(pNodeRight); } } return S_OK; } template HRESULT StlDbgMap::HrDumpAll(LPVOID lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack) { return HrDumpAllFromUl64((ULONG64)(ULONG_PTR)(lpAddress), lpParam, pFNDumpFnCallBack); } template HRESULT StlDbgList::HrDumpAll(LPVOID lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack) { return HrDumpAllFromUl64((ULONG64)(ULONG_PTR)(lpAddress), lpParam, pFNDumpFnCallBack); } template HRESULT StlDbgMap::HrDumpAllFromUl64(ULONG64 lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack) { HRESULT hr = E_FAIL; C_ASSERT(sizeof(T) == sizeof(StlDbgMap)); // If you have a compile error on this line it means you added non-static data to your class. // This is not allowed as it will break the binary compatibility of the structure. StlDbgMap *pStlDbgCore; hr = HrInitialRead(lpAddress, reinterpret_cast **>(&pStlDbgCore)); if (S_OK == hr) // don't care if 0 entries { _StlDbgNodePtr pStlDbgHeadNode = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pStlDbgHeadNode) { ZeroMemory(pStlDbgHeadNode, sizeof(_StlDbgNode)); dprintfVerbose("Reading map<>.[_Tr]._Head"); hr = HrReadMemory(pStlDbgCore->_Tr._Head, sizeof(_StlDbgNode), pStlDbgHeadNode); if (SUCCEEDED(hr)) { _StlDbgNodePtr pDbgMapRootNode = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pDbgMapRootNode) { ZeroMemory(pDbgMapRootNode, sizeof(_StlDbgNode)); dprintfVerbose("Reading map<>.[_Tr]._Head._Parent"); hr = HrReadMemory( pStlDbgHeadNode->_Parent, sizeof(_StlDbgNode), pDbgMapRootNode); if (SUCCEEDED(hr)) { hr = HrDumpNode(pDbgMapRootNode, pStlDbgHeadNode->_Parent, 0, lpParam, pFNDumpFnCallBack); } delete [] reinterpret_cast(pDbgMapRootNode); } } delete [] reinterpret_cast(pStlDbgHeadNode); } delete reinterpret_cast(pStlDbgCore); } return hr; } template HRESULT StlDbgList::HrDumpAllFromUl64(ULONG64 lpAddress, LPVOID lpParam, FNDumpFnCallBack* pFNDumpFnCallBack) { HRESULT hr = E_FAIL; C_ASSERT(sizeof(T) == sizeof(StlDbgList)); // If you have a compile error on this line it means you added non-static data to your class. // This is not allowed as it will break the binary compatibility of the structure. StlDbgList *pStlDbgCore; hr = HrInitialRead(lpAddress, reinterpret_cast **>(&pStlDbgCore)); if (S_OK == hr) // don't care if 0 entries { _StlDbgNodePtr pStlDbgHeadNode = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pStlDbgHeadNode) { ZeroMemory(pStlDbgHeadNode, sizeof(_StlDbgNode)); dprintfVerbose("Reading list<>._Head"); hr = HrReadMemory(pStlDbgCore->_Head, sizeof(_StlDbgNode), pStlDbgHeadNode); if (SUCCEEDED(hr)) { _StlDbgNodePtr pStlDbgNodeNext = reinterpret_cast<_StlDbgNodePtr>(new BYTE[sizeof(_StlDbgNode)]); if (pStlDbgNodeNext) { BOOL fDone = FALSE; dprintfVerbose("Reading list<>._Head->_Next"); hr = HrReadMemory(pStlDbgHeadNode->_Next, sizeof(_StlDbgNode), pStlDbgNodeNext); LPVOID ulReadAddress = pStlDbgNodeNext->_Value; while (SUCCEEDED(hr) && !fDone) { dprintfVerbose("dumping list entry at from 0x%08x\r\n", pStlDbgNodeNext->_Value); hr = pFNDumpFnCallBack(lpParam, NULL, pStlDbgNodeNext->_Value, ulReadAddress); if (SUCCEEDED(hr)) { if (pStlDbgNodeNext->_Next == pStlDbgCore->_Head) { dprintfVerbose("end of list\n"); fDone = TRUE; } else { hr = HrReadMemory(pStlDbgNodeNext->_Next, sizeof(_StlDbgNode), pStlDbgNodeNext); ulReadAddress = pStlDbgNodeNext->_Value; } } } } } delete [] reinterpret_cast(pStlDbgHeadNode); } delete reinterpret_cast(pStlDbgCore); } return hr; } template HRESULT StlDbgBase::HrInitialRead(ULONG64 lpAddress, StlDbgBase** lpHeader) { HRESULT hr = E_FAIL; C_ASSERT(sizeof(T) == sizeof(StlDbgBase));// If you have a compile error on this line it means you added non-static data to your class. // This is not allowed as it will break the binary compatibility of the structure. StlDbgBase *pStlDbgCore = reinterpret_cast *>(new BYTE[sizeof(StlDbgBase)]); if (pStlDbgCore) { ZeroMemory(pStlDbgCore, sizeof(StlDbgBase)); dprintfVerbose("Reading STL class starting at %08x", lpAddress); hr = HrReadMemoryFromUlong(lpAddress, sizeof(StlDbgBase), pStlDbgCore); if (SUCCEEDED(hr)) { dprintf("%d entries found:\n", pStlDbgCore->size()); if (pStlDbgCore->size()) { hr = S_OK; } else { hr = S_FALSE; } } if (SUCCEEDED(hr)) { *lpHeader = pStlDbgCore; } else { delete reinterpret_cast(pStlDbgCore); } } return hr; }