867 lines
24 KiB
C++
867 lines
24 KiB
C++
/*-----------------------------------------------------------------------------
|
|
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"
|
|
);
|
|
|
|
}
|
|
|