|
|
/*-----------------------------------------------------------------------------
Copyright (c) 2000 Microsoft Corporation
Module: ncext.c
------------------------------------------------------------------------------*/
#define ENABLETRACE
#define NCDBGEXT
#define IMPORT_NCDBG_FRIENDS \
friend HRESULT HrDumpConnectionListFromAddress(ULONG64 address); \ friend HRESULT HrDumpNode(LPVOID pvHead, LPVOID pvDbgHead, LPVOID pvNil, DWORD dwLevel);
#include "ncext.h"
// #define VERBOSE
#include "ncmem.h"
#include "ncbase.h"
#include "ncdebug.h"
#include "ncdefine.h"
#include "tracetag.h"
#include "naming.h"
#include "foldinc.h"
#include "connlist.h"
#ifdef VERBOSE
#define dprintfVerbose dprintf
#else
#define dprintfVerbose __noop
#endif
HRESULT HrGetAddressOfSymbol(LPCSTR szSymbol, PULONG64 pAddress) { HRESULT hr = E_FAIL;
if (pAddress) { *pAddress = 0; }
if (!szSymbol || !*szSymbol || !pAddress) { hr = E_INVALIDARG; } else { *pAddress = GetExpression(szSymbol); if (!*pAddress) { dprintf("\nCould not find symbol: %s. Is your symbols correct?\n", szSymbol); } else { dprintfVerbose("%s: %I64lx\n", szSymbol, *pAddress); hr = S_OK; } } return hr; }
HRESULT HrGetAddressOfSymbol(LPCSTR szModule, LPCSTR szSymbol, PULONG64 pAddress) { HRESULT hr = E_FAIL;
if (pAddress) { *pAddress = 0; }
if (!szModule || !*szModule || !szSymbol || !*szSymbol || !pAddress) { hr = E_INVALIDARG; } else { *pAddress = 0;
CHAR szModulueSymbol[MAX_PATH]; wsprintf(szModulueSymbol, "%s!%s", szModule, szSymbol); dprintfVerbose("%s: ", szModulueSymbol);
hr = HrGetAddressOfSymbol(szModulueSymbol, pAddress); }
return hr; }
HRESULT HrReadMemoryFromUlong(ULONG64 Address, DWORD dwSize, OUT LPVOID pBuffer) { HRESULT hr = S_OK; DWORD cb;
dprintfVerbose("from %I64lx, size=%x\n", Address, dwSize); if (ReadMemory(Address, pBuffer, dwSize, &cb) && cb == dwSize) { hr = S_OK; } else { dprintf("Could not read content of memory at %I64lx. Content might be paged out.\n", Address); hr = E_FAIL; } return hr; }
HRESULT HrWriteMemoryFromUlong(ULONG64 Address, DWORD dwSize, OUT LPCVOID pBuffer) { HRESULT hr = S_OK; DWORD cb;
dprintfVerbose("to %I64lx, size=%x\n", Address, dwSize); if (WriteMemory(Address, pBuffer, dwSize, &cb) && cb == dwSize) { hr = S_OK; } else { dprintf("Could not write content of memory to %I64lx. Address might be paged out.\n", Address); hr = E_FAIL; } return hr; }
HRESULT HrReadMemory(LPVOID pAddress, DWORD dwSize, OUT LPVOID pBuffer) { return HrReadMemoryFromUlong((ULONG64)(ULONG_PTR)pAddress, dwSize, pBuffer); }
HRESULT HrWriteMemory(LPVOID pAddress, DWORD dwSize, OUT LPCVOID pBuffer) { return HrWriteMemoryFromUlong((ULONG64)(ULONG_PTR)pAddress, dwSize, pBuffer); }
HRESULT HrGetTraceTagsForModule(LPCSTR szModuleName, LPDWORD pdwCount, TRACETAGELEMENT** ppTRACETAGELEMENT) { HRESULT hr = E_FAIL;
if (szModuleName && *szModuleName) { ULONG64 g_TraceTagCountAddress = 0; ULONG64 g_TraceTagsAddress = 0; hr = HrGetAddressOfSymbol(szModuleName, "g_nTraceTagCount", &g_TraceTagCountAddress); if (SUCCEEDED(hr)) { INT nTraceTagCount = 0; hr = HrReadMemoryFromUlong(g_TraceTagCountAddress, sizeof(nTraceTagCount), &nTraceTagCount); if (SUCCEEDED(hr)) { *pdwCount = nTraceTagCount; dprintfVerbose("Number of tags: %d\n", nTraceTagCount); hr = HrGetAddressOfSymbol(szModuleName, "g_TraceTags", &g_TraceTagsAddress); if (SUCCEEDED(hr)) { if (nTraceTagCount) { DWORD dwSize = nTraceTagCount * sizeof(TRACETAGELEMENT); *ppTRACETAGELEMENT = reinterpret_cast<TRACETAGELEMENT*>(LocalAlloc(0, dwSize)); if (*ppTRACETAGELEMENT) { dprintfVerbose("Reading %d bytes\n", dwSize);
hr = HrReadMemoryFromUlong(g_TraceTagsAddress, dwSize, *ppTRACETAGELEMENT); } else { dprintf("Out of memory allocating %d trace elements\n", nTraceTagCount); } } else { dprintf("Internal error\n"); } } } else { dprintf("*ERROR* Could not read content of %s!g_nTraceTagCount. Value might be paged out.\n", szModuleName); } } }
return hr; }
HRESULT HrPutTraceTagsForModule(LPCSTR szModuleName, DWORD dwCount, const TRACETAGELEMENT* pTRACETAGELEMENT) { HRESULT hr = E_FAIL;
if (szModuleName && *szModuleName) { CHAR szTraceExport[MAX_PATH]; wsprintf(szTraceExport, "%s!g_TraceTags", szModuleName); dprintfVerbose("%s: ", szTraceExport);
ULONG64 pnTraceAddress = GetExpression(szTraceExport); if (!pnTraceAddress) { dprintf("\n### Could not find g_TraceTags export on module %s. Is %s loaded, and is your symbols correct? ###\n", szModuleName, szModuleName); } dprintfVerbose("%I64lx\n", pnTraceAddress);
CHAR szTraceCount[MAX_PATH]; wsprintf(szTraceCount, "%s!g_nTraceTagCount", szModuleName); dprintfVerbose("%s: ", szTraceCount); ULONG64 pnTraceTagCount = GetExpression(szTraceCount); if (!pnTraceTagCount) { dprintf("\n### Could not find g_nTraceTagCount export on module %s. Is %s loaded, and is your symbols correct? ###\n", szModuleName, szModuleName); } dprintfVerbose("%I64lx\n", pnTraceTagCount);
if (pnTraceAddress & pnTraceTagCount) { INT nTraceTagCount = 0; DWORD cb; hr = HrReadMemoryFromUlong(pnTraceTagCount, sizeof(nTraceTagCount), &nTraceTagCount); if (SUCCEEDED(hr)) { dwCount = nTraceTagCount; if (dwCount != nTraceTagCount) { dprintf("Internal Error\n"); } else { dprintfVerbose("Number of tags: %d\n", nTraceTagCount); if (nTraceTagCount) { DWORD dwSize = nTraceTagCount * sizeof(TRACETAGELEMENT); dprintfVerbose("Writing %d bytes\n", dwSize); hr = HrWriteMemoryFromUlong(pnTraceAddress, dwSize, pTRACETAGELEMENT); } else { dprintf("Internal error\n"); } } } else { dprintf("*ERROR* Could not read content of %s!g_nTraceTagCount. Value might be paged out.\n", szModuleName); } } }
return hr; }
//
// Extension to read and dump dwords from target
//
DECLARE_API( tracelist ) { ULONG cb; ULONG64 Address; ULONG Buffer[4];
if (!lstrcmpi(args, "all")) { for (int x = 0; x < g_nTraceTagCount; x++) { dprintf("%-20s - %s\r\n", g_TraceTags[x].szShortName, g_TraceTags[x].szDescription); } } else { if (args && *args) { DWORD dwCount; TRACETAGELEMENT *pTRACETAGELEMENT; HRESULT hr = HrGetTraceTagsForModule(args, &dwCount, &pTRACETAGELEMENT); if (SUCCEEDED(hr)) { for (DWORD x = 0; x < dwCount; x++) { if (pTRACETAGELEMENT[x].fOutputDebugString) { dprintf(" %s\n", pTRACETAGELEMENT[x].szShortName); } }
LocalFree(pTRACETAGELEMENT); } } else { dprintf("Usage: !tracelist all - dump all tracetags\n"); dprintf(" !tracelist <module> - dump tracetags enable for module <module>\n"); } } }
HRESULT HrEnableDisableTraceTag(LPCSTR argstring, BOOL fEnable) { HRESULT hr = E_FAIL;
BOOL fShowUsage = FALSE; DWORD dwArgLen = lstrlen(argstring);
if (dwArgLen) { LPSTR szString = new TCHAR[dwArgLen+1]; if (!szString) { dprintf("Out of memory\n"); } else { LPSTR Args[2]; DWORD dwCurrentArg = 0; lstrcpy(szString, argstring); Args[0] = szString; for (DWORD x = 0; (x < dwArgLen) && (dwCurrentArg < celems(Args)); x++) { if (szString[x] == ' ') { dwCurrentArg++;
szString[x] = '\0'; Args[dwCurrentArg] = szString + x + 1; } }
dprintfVerbose("Number of arguments: %d\n", dwCurrentArg + 1);
if (dwCurrentArg != 1) { hr = E_INVALIDARG; } else { dprintfVerbose("Arguments: %s, %s\n", Args[0], Args[1]); if (argstring && *argstring) { DWORD dwCount; TRACETAGELEMENT *pTRACETAGELEMENT; HRESULT hr = HrGetTraceTagsForModule(Args[0], &dwCount, &pTRACETAGELEMENT); if (SUCCEEDED(hr)) { BOOL fFound = FALSE; for (DWORD x = 0; x < dwCount; x++) { if (!lstrcmpi(Args[1], pTRACETAGELEMENT[x].szShortName)) { fFound = TRUE;
if (pTRACETAGELEMENT[x].fOutputDebugString == fEnable) { dprintf(" [%s] is already %s\n", pTRACETAGELEMENT[x].szShortName, fEnable ? "enabled" : "disabled"); hr = S_FALSE; } else { pTRACETAGELEMENT[x].fOutputDebugString = fEnable; if (SUCCEEDED(HrPutTraceTagsForModule(Args[0], dwCount, pTRACETAGELEMENT))) { dprintf(" [%s] is now %s on module %s\n", pTRACETAGELEMENT[x].szShortName, fEnable ? "enabled" : "disabled", Args[0]); hr = S_OK; } break; } } }
if (!fFound) { dprintf("ERROR: No such TraceTag ID found in module %s\n", Args[0]); }
LocalFree(pTRACETAGELEMENT); } } else { } } }
delete [] szString; } else { hr = E_INVALIDARG; } return hr; }
//
// Extension to edit a dword on target
//
// !edit <address> <value>
//
DECLARE_API( traceadd ) { ULONG cb; ULONG64 Address; ULONG Value;
HRESULT hr = HrEnableDisableTraceTag(args, TRUE);
if (E_INVALIDARG == hr) { dprintf("Usage: traceadd <module> \"tracetag\" - Starts tracing for a specific tracetag\n"); } }
//
// Extension to dump stacktrace
//
DECLARE_API ( tracedel ) { EXTSTACKTRACE64 stk[20]; ULONG frames, i; CHAR Buffer[256]; ULONG64 displacement;
HRESULT hr = HrEnableDisableTraceTag(args, FALSE);
if (E_INVALIDARG == hr) { dprintf("Usage: tracedel <module> \"tracetag\" - Stops tracing for a specific tracetag\n"); } }
typedef map<ConnListCore::key_type, ConnListCore::referent_type> ConnListCoreMap;
class ConnList_Map : public ConnListCoreMap { public: class ConnList_Tree : public ConnListCoreMap::_Imp { public: _Nodeptr GetHead() { return _Head; } _Nodepref _Left(_Nodeptr _P) { return ((_Nodepref)(*_P)._Left); } _Nodepref _Right(_Nodeptr _P) { return ((_Nodepref)(*_P)._Right); }
LPVOID _GetHeadPtr() { return _Head; } LPVOID _LeftPtr(LPVOID _P) { return ((* (_Nodeptr)_P)._Left); } LPVOID _RightPtr(LPVOID _P) { return ((* (_Nodeptr)_P)._Right); } LPVOID _ParentPtr(LPVOID _P) { return ((* (_Nodeptr)_P)._Parent); } LPVOID GetNil() { return _Nil; } DWORD _GetNodeSize() { return sizeof(_Node); } };
public: ConnList_Tree *GetTree() { return reinterpret_cast<ConnList_Tree *>(&_Tr); }
LPVOID _GetHeadPtr() { return GetTree()->_GetHeadPtr(); } LPVOID _LeftPtr(LPVOID p) { return GetTree()->_LeftPtr(p); } LPVOID _RightPtr(LPVOID p) { return GetTree()->_RightPtr(p); } LPVOID _ParentPtr(LPVOID p) { return GetTree()->_ParentPtr(p); } LPVOID GetNil() { return GetTree()->GetNil(); } DWORD _GetNodeSize() { return GetTree()->_GetNodeSize(); } typedef ConnList_Tree::_Node _NodeType; };
typedef ConnList_Map::_NodeType NodeType;
LPCSTR DBG_EMNAMES[] = { "INVALID_EVENTMGR", "EVENTMGR_CONMAN", "EVENTMGR_EAPOLMAN" };
LPCSTR DBG_CMENAMES[] = { "INVALID_TYPE", "CONNECTION_ADDED", "CONNECTION_BANDWIDTH_CHANGE", "CONNECTION_DELETED", "CONNECTION_MODIFIED", "CONNECTION_RENAMED", "CONNECTION_STATUS_CHANGE", "REFRESH_ALL", "CONNECTION_ADDRESS_CHANGE" };
LPCSTR DBG_NCMNAMES[] = { "NCM_NONE", "NCM_DIRECT", "NCM_ISDN", "NCM_LAN", "NCM_PHONE", "NCM_TUNNEL", "NCM_PPPOE", "NCM_BRIDGE", "NCM_SHAREDACCESSHOST_LAN", "NCM_SHAREDACCESSHOST_RAS" };
LPCSTR DBG_NCSMNAMES[] = { "NCSM_NONE", "NCSM_LAN", "NCSM_WIRELESS", "NCSM_ATM", "NCSM_ELAN", "NCSM_1394", "NCSM_DIRECT", "NCSM_IRDA", "NCSM_CM", };
LPCSTR DBG_NCSNAMES[] = { "NCS_DISCONNECTED", "NCS_CONNECTING", "NCS_CONNECTED", "NCS_DISCONNECTING", "NCS_HARDWARE_NOT_PRESENT", "NCS_HARDWARE_DISABLED", "NCS_HARDWARE_MALFUNCTION", "NCS_MEDIA_DISCONNECTED", "NCS_AUTHENTICATING", "NCS_AUTHENTICATION_SUCCEEDED", "NCS_AUTHENTICATION_FAILED", "NCS_INVALID_ADDRESS", "NCS_CREDENTIALS_REQUIRED" };
// Shorten these to fit more in.
LPCSTR DBG_NCCSFLAGS[] = { "_NONE", "_ALL_USERS", "_ALLOW_DUPLICATION", "_ALLOW_REMOVAL", "_ALLOW_RENAME", "_SHOW_ICON", "_INCOMING_ONLY", "_OUTGOING_ONLY", "_BRANDED", "_SHARED", "_BRIDGED", "_FIREWALLED", "_DEFAULT" };
LPCSTR DbgEvents(DWORD Event) { if (Event < celems(DBG_CMENAMES)) { return DBG_CMENAMES[Event]; } else { return "UNKNOWN Event: Update DBG_CMENAMES table."; } }
LPCSTR DbgEventManager(DWORD EventManager) { if (EventManager < celems(DBG_EMNAMES)) { return DBG_EMNAMES[EventManager]; } else { return "UNKNOWN Event: Update DBG_EMNAMES table."; } }
LPCSTR DbgNcm(DWORD ncm) { if (ncm < celems(DBG_NCMNAMES)) { return DBG_NCMNAMES[ncm]; } else { return "UNKNOWN NCM: Update DBG_NCMNAMES table."; } }
LPCSTR DbgNcsm(DWORD ncsm) { if (ncsm < celems(DBG_NCSMNAMES)) { return DBG_NCSMNAMES[ncsm]; } else { return "UNKNOWN NCM: Update DBG_NCSMNAMES table."; } }
LPCSTR DbgNcs(DWORD ncs) { if (ncs < celems(DBG_NCSNAMES)) { return DBG_NCSNAMES[ncs]; } else { return "UNKNOWN NCS: Update DBG_NCSNAMES table."; } }
LPCSTR DbgNccf(DWORD nccf) { static CHAR szName[MAX_PATH];
if (nccf >= (1 << celems(DBG_NCCSFLAGS)) ) { return "UNKNOWN NCCF: Update DBG_NCCSFLAGS table."; }
if (0 == nccf) { strcpy(szName, DBG_NCCSFLAGS[0]); } else { szName[0] = '\0'; LPSTR szTemp = szName; BOOL bFirst = TRUE; for (DWORD x = 0; x < celems(DBG_NCCSFLAGS); x++) { if (nccf & (1 << x)) { if (!bFirst) { szTemp += sprintf(szTemp, "+"); } else { szTemp += sprintf(szTemp, "NCCF:"); } bFirst = FALSE; szTemp += sprintf(szTemp, "%s", DBG_NCCSFLAGS[x+1]); } } }
return szName; }
HRESULT HrDumpNode(LPVOID pvHead, LPVOID pvDbgHead, LPVOID pvNil, DWORD dwLevel) { NodeType *pHead = reinterpret_cast<NodeType *>(pvHead); dprintfVerbose("%d: [0x%I64lx], NIL = [0x%I64lx]\n", dwLevel, pvDbgHead, pvNil); if (pvDbgHead == pvNil) { 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; ConnListEntry &cle = pHead->_Value.second; CConFoldEntry &cfe = cle.ccfe;
WCHAR szNameEntry[MAX_PATH]; dprintfVerbose("%d: Reading szNameEntry", dwLevel); hr = HrReadMemory(cfe.m_pszName, celems(szNameEntry), szNameEntry); if (SUCCEEDED(hr)) { if (*szNameEntry) { LPWSTR szGUID; StringFromCLSID(cfe.m_guidId, &szGUID);
dprintf(" * %S [%s:%s:%s:%s]\n", szNameEntry, DbgNcs(cfe.m_ncs), DbgNccf(cfe.m_dwCharacteristics), DbgNcm(cfe.m_ncm), DbgNcsm(cfe.m_ncsm) ); dprintf(" guidId : %S\n", szGUID); CoTaskMemFree(szGUID);
StringFromCLSID(cfe.m_clsid, &szGUID); dprintf(" clsId : %S\n", szGUID); CoTaskMemFree(szGUID);
hr = HrReadMemory(cfe.m_pszDeviceName , celems(szNameEntry), szNameEntry); if (SUCCEEDED(hr)) { dprintf(" Device Name : %S\n", szNameEntry); }
hr = HrReadMemory(cfe.m_pszPhoneOrHostAddress, celems(szNameEntry), szNameEntry); if (SUCCEEDED(hr)) { dprintf(" Phone # : %S\n", szNameEntry); } switch (cfe.m_wizWizard) { case WIZARD_NOT_WIZARD: break; case WIZARD_HNW: dprintf(" WIZARD_HNW\n"); break; case WIZARD_MNC: dprintf(" WIZARD_MNC\n"); break; } } }
dprintfVerbose("%d: left is : 0x%I64lx\n", dwLevel, pHead->_Left); dprintfVerbose("%d: right is: 0x%I64lx\n", dwLevel, pHead->_Right); if (0 != pHead->_Left) { NodeType *pNodeLeft = reinterpret_cast<NodeType *>(new BYTE[sizeof(NodeType)]); ZeroMemory(pNodeLeft, sizeof(NodeType)); dprintfVerbose("%d: Reading left child node ", dwLevel); hr = HrReadMemory(pHead->_Left, sizeof(NodeType), pNodeLeft); if (SUCCEEDED(hr)) { hr = ::HrDumpNode(pNodeLeft, pHead->_Left, pvNil, dwLevel+1); } delete [] reinterpret_cast<LPBYTE>(pNodeLeft); }
if (0 != pHead->_Right) { NodeType *pNodeRight = reinterpret_cast<NodeType *>(new BYTE[sizeof(NodeType)]); ZeroMemory(pNodeRight, sizeof(NodeType)); dprintfVerbose("%d: Reading right child node ", dwLevel); hr = HrReadMemory(pHead->_Right, sizeof(NodeType), pNodeRight); if (SUCCEEDED(hr)) { hr = ::HrDumpNode(pNodeRight, pHead->_Right, pvNil, dwLevel+1); } delete [] reinterpret_cast<LPBYTE>(pNodeRight); } return S_OK; }
HRESULT HrDumpConnectionListFromAddress(ULONG64 address) { HRESULT hr = E_FAIL;
CConnectionList *pConnectionList = reinterpret_cast<CConnectionList *>(new BYTE[sizeof(CConnectionList)]); ZeroMemory(pConnectionList, sizeof(CConnectionList));
dprintfVerbose("Reading pConnectionList (g_ccl) "); hr = HrReadMemoryFromUlong(address, sizeof(CConnectionList), pConnectionList); if (SUCCEEDED(hr)) { ConnList_Map *pConnListCore = reinterpret_cast<ConnList_Map *>(new BYTE[sizeof(ConnList_Map)]); ZeroMemory(pConnListCore, sizeof(ConnList_Map));
dprintfVerbose("Reading pConnListCore (g_ccl.m_pcclc) "); hr = HrReadMemory(pConnectionList->m_pcclc, sizeof(ConnList_Map), pConnListCore); if (SUCCEEDED(hr)) { dprintf("%d entries found:\n", pConnListCore->size());
NodeType *pConnListHead = reinterpret_cast<NodeType *>(new BYTE[sizeof(NodeType)]); ZeroMemory(pConnListHead, sizeof(NodeType));
dprintfVerbose("Reading pConnListHead (g_ccl.m_pcclc.[_Tr]._Head) "); hr = HrReadMemory(pConnListCore->_GetHeadPtr(), sizeof(NodeType), pConnListHead); if (SUCCEEDED(hr)) { // hr = ::HrDumpNode(pConnListHead, 0);
NodeType *pConnListRoot = reinterpret_cast<NodeType *>(new BYTE[sizeof(NodeType)]); ZeroMemory(pConnListRoot, sizeof(NodeType)); dprintfVerbose("Reading pConnListRoot (g_ccl.m_pcclc.[_Tr]._Head._Parent) "); hr = HrReadMemory(pConnListHead->_Parent, sizeof(NodeType), pConnListRoot); if (SUCCEEDED(hr)) { hr = ::HrDumpNode(pConnListRoot, pConnListHead->_Parent, pConnListCore->GetNil(), 0); } delete [] reinterpret_cast<LPBYTE>(pConnListRoot); } delete [] reinterpret_cast<LPBYTE>(pConnListHead); } delete reinterpret_cast<LPBYTE>(pConnListCore); } delete reinterpret_cast<LPBYTE>(pConnectionList);
if (FAILED(hr)) { dprintf("Could not dump connection list\n"); } return hr; }
//
// Extension to dump stacktrace
//
DECLARE_API ( connlist ) { EXTSTACKTRACE64 stk[20]; ULONG frames, i; CHAR Buffer[256]; ULONG64 displacement;
HRESULT hr = E_FAIL;; ULONG64 g_cclAddress; if (*args) { hr = HrGetAddressOfSymbol(args, &g_cclAddress); } else { hr = HrGetAddressOfSymbol("netshell!g_ccl", &g_cclAddress); }
if (SUCCEEDED(hr)) { hr = ::HrDumpConnectionListFromAddress(g_cclAddress); }
if (E_INVALIDARG == hr) { dprintf("Usage:\n" " connlist - Dumps out the connection\n" " connlist <address> - Dumps out the connection list from address\n"); } }
/*
A built-in help for the extension dll */
DECLARE_API ( help ) { dprintf("Help for NetConfig ncext.dll\n" " tracelist <module> - List all the currently traces enabled for module <module>\n" " tracelist all - List currently available traces\n" " traceadd <module> \"tracetag\" - Starts tracing for a specific tracetag\n" " tracedel <module> \"tracetag\" - Stops tracing for a specific tracetag\n" " connlist - Dumps out the connection\n" " connlist <address> - Dumps out the connection list from address\n" " help - Shows this help\n" );
}
|