📄 memtrk.c
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. */
// @doc EXTERNAL KERNEL
#include "kernel.h"
#include "excpt.h"
#include "memtrack.h"
#if !defined(MIPS) && !defined(SHx)
#undef MEMTRACKING
#endif
/*
@topic Resource tracking Support for Applications |
The kernel provides support for registering and tracking any kind
of resource. If you are trying to register and track resources in
your program you will need to look at the <f RegisterTrackedItem>,
<f AddTrackedItem> and <f DeleteTrackedItem> calls. If you are a
user trying to use the tracking to find leaks, you will need to
study the <f FilterTrackedItem> and <f PrintTrackedItem> calls. The
WinCE shell has been enhanced to give you a command line interface
to these calls. You can make a function to print the tracked item
using <f TrackerCallBack>.
*/
#ifdef MEMTRACKING
CALLBACKINFO cbi;
pTrack_Node pnFirst; // index of first add in sequence
pTrack_Node pnLast; // index of last add in sequence
LPMEMTR_ITEMTYPE rgRegTypes; // registered types
LPMEMTR_FILTERINFO lpFilterInfo; // filter information
pTrack_Node table; // hash table
UINT uiTablesize, Count; // size of hash table
#pragma message("MemTracking")
typedef struct _NameandBase {
LPCHAR szName;
UINT ImageBase;
UINT ImageSize;
} NAMEANDBASE, *PNAMEANDBASE;
#if MIPS
#define STK_ALIGN 0x7
#define INST_SIZE 4
#define STACKPTR IntSp
#define RETADDR IntRa
PRUNTIME_FUNCTION NKLookupFunctionEntry(PPROCESS pProc, ULONG ControlPc);
#define LookupFunctionEntry(a,b) NKLookupFunctionEntry((a),(b))
#elif SHx
#define STK_ALIGN 0x3
#define INST_SIZE 2
#define STACKPTR R15
#define RETADDR PR
PRUNTIME_FUNCTION NKLookupFunctionEntry(PPROCESS pProc, ULONG ControlPc, PRUNTIME_FUNCTION prf);
RUNTIME_FUNCTION TempFunctionEntry;
#define LookupFunctionEntry(a,b) NKLookupFunctionEntry((a),(b),(&TempFunctionEntry))
#endif
#define NKGetStackLimits(pth, LL, HL) ((*(LL) = (pth)->dwStackBase), (*(HL) = (ULONG)(pth)->tlsPtr))
void UpdateASID(IN PTHREAD pth, IN PPROCESS pProc, IN ACCESSKEY aky);
LPMODULE MEMTR_ModuleFromAddress(DWORD dwAdd);
LPWSTR MEMTR_GetWin32ExeName(PPROCESS pProc);
CONTEXT CurrentContext;
CRITICAL_SECTION Trackcs;
BOOL MemTrackInit2(void) {
LPBYTE lpbMem;
DWORD dwUsed;
RETAILMSG(1, (L"InInit\r\n"));
DEBUGMSG(ZONE_MEMTRACKER, (L"Len : %8.8lx Start: %8.8lx\r\n",
pTOC->ulTrackingLen, pTOC->ulTrackingStart));
if (!pTOC->ulTrackingLen || !pTOC->ulTrackingStart)
{
return FALSE;
}
RETAILMSG(1, (L"StillInInit!!\r\n"));
if (!(lpbMem = (LPBYTE)VirtualAlloc(0, pTOC->ulTrackingLen, MEM_RESERVE, PAGE_NOACCESS)))
{
ERRORMSG(1, (L"VirtualAlloc failed (%8.8lx) for memtracking\r\n", GetLastError()));
return FALSE;
}
if (!VirtualCopy(lpbMem, (LPVOID)pTOC->ulTrackingStart, pTOC->ulTrackingLen, PAGE_READWRITE)) {
VirtualFree(lpbMem, 0, MEM_RELEASE);
ERRORMSG(1, (L"VirtualCopy failed (%8.8lx) for memtracking\r\n", GetLastError()));
return FALSE;
}
lpbMem = MapPtr(lpbMem);
memset(lpbMem, 0, pTOC->ulTrackingLen);
dwUsed = 0;
// now divy up the memory we got - the table soaks up all available left in the end
lpFilterInfo = (LPMEMTR_FILTERINFO)(lpbMem+dwUsed);
// initialize to start off with no tracking
lpFilterInfo->dwFlags |= FILTER_TYPEDEFAULTOFF;
dwUsed += sizeof(MEMTR_FILTERINFO);
rgRegTypes = (LPMEMTR_ITEMTYPE)(lpbMem+dwUsed);
dwUsed += MAX_REGTYPES*sizeof(MEMTR_ITEMTYPE);
table = (pTrack_Node)(lpbMem+dwUsed);
uiTablesize = (pTOC->ulTrackingLen-dwUsed) / sizeof(Track_Node);
DEBUGMSG(ZONE_MEMTRACKER, (L"Size %8.8lx Sizeof %8.8lx\r\n",
uiTablesize, (DWORD)sizeof(Track_Node)));
return TRUE;
}
// init: initialize hash table, sequence pointers
void MemTrackInit(void)
{
InitializeCriticalSection(&Trackcs);
cbi.hProc = ProcArray[0].hProc;
cbi.pfn = (FARPROC)MemTrackInit2;
cbi.pvArg0 = 0;
}
#endif
/*
@func DWORD | RegisterTrackedItem | Registers a type of resource to be tracked
@parm LPWSTR | szName | A friendly name for the resource to be tracked. Must be less than 16
characters. If this is NULL a list of all currently registered types is printed on the
debug terminal.
@rdesc The typeid which this resource has been alloted. You should use this in all other calls.
@comm Before you can track any resource, you must register it's type and get back a dword
TypeID for it. This typeid is used in all other resource tracker calls. Each resource
is guaranteed a unique resource type. If a resource with the exact same name exists
it's type id is returned. This allows DLL's to register the same type multiple times
in their PROCESS_ATTACH while keeping the same TypeID.
@xref <f FilterTrackedItem> <f AddTrackedItem> <f PrintTrackedItem> <f DeleteTrackedItem> <f TrackerCallBack>
*/
DWORD SC_RegisterTrackedItem(LPWSTR szName)
{
DWORD dwRet = (DWORD)-1;
#ifdef MEMTRACKING
int i,j;
LPWSTR lpwTgt, lpwSrc;
EnterCriticalSection(&Trackcs);
if (!pTOC->ulTrackingLen || !pTOC->ulTrackingStart)
{
goto errret;
}
if (!uiTablesize && !PerformCallBack4(&cbi,0))
goto errret;
if (!szName) {
RETAILMSG(1, (L"Registered types: Default tracking state is %s\r\n",
(lpFilterInfo->dwFlags&FILTER_TYPEDEFAULTOFF)? L"Off": L"On"));
RETAILMSG(1, (L" Resource Name :TypeID:Tracking\r\n"));
for (i=0; i<MAX_REGTYPES && rgRegTypes[i].dwFlags; i++) {
RETAILMSG(1, (L" %-32.32s:%6.6u:%s\r\n", rgRegTypes[i].szName, i,
(rgRegTypes[i].dwFlags®TYPE_MASKED)? L" Off ":L" On "));
}
goto errret;
}
for (i=0; i<MAX_REGTYPES && rgRegTypes[i].dwFlags; i++) {
lpwTgt=rgRegTypes[i].szName;
lpwSrc=szName;
while(*lpwTgt && (*lpwTgt++==*lpwSrc++));
if (!*lpwTgt && !*lpwSrc) {
DEBUGMSG(ZONE_MEMTRACKER, (TEXT("Tracking: Name %s found at %u\r\n"), rgRegTypes[i].szName, i));
dwRet = i;
goto errret;
}
}
if (i<MAX_REGTYPES) {
// copy the name (cant use coredll string functions here)
j=MAX_REGTYPENAMESIZE;
lpwTgt=rgRegTypes[i].szName;
while(--j && (*lpwTgt++=*szName++));
*lpwTgt = 0;
rgRegTypes[i].dwFlags = (lpFilterInfo->dwFlags&FILTER_TYPEDEFAULTOFF)?
REGTYPE_MASKED|REGTYPE_INUSE : REGTYPE_INUSE;
DEBUGMSG(ZONE_MEMTRACKER, (TEXT("Tracking: Name %s type %u\r\n"), rgRegTypes[i].szName, i));
dwRet = i;
} else {
ERRORMSG(1, (TEXT("MEMTRACK: Couldnt register type. Name ptr 0x%08X"), szName));
}
errret:
LeaveCriticalSection(&Trackcs);
#endif
return dwRet;
}
/*
@func VOID | FilterTrackedItem | Installs filters on AddTrackedItem
@parm DWORD | dwFlags | A combination of the following
@flag FILTER_TYPEDEFAULTON | Unmasks all types of resource regardless of their
previous state. Any new resource will also start off unmasked.
@flag FILTER_TYPEDEFAULTOFF | All resource types are masked out. Any new resources
will also start off masked off.
@flag FILTER_TYPEON | Unmasks the resource type specified in <p dwType>. This flag
is processed after the default flag
@flag FILTER_TYPEOFF | Masks the resource type specified in <p dwType>. This flag
is processed after the default flag
@flag FILTER_PROCIDON | Installs a filter so that only resources for <p dwProcID>
are tracked.
@flag FILTER_PROCIDOFF | Removes any installed process filters.
@parm DWORD | dwType | TypeID if the FILTER_TYPEON or FILTER_TYPEOFF flag is specified
@parm DWORD | dwProcID | ProcID if the FILTER_PROCIDON flag is specified
@comm You can use this function to restrict the number of resources being tracked in the
system. These filters will cause any resource items not matching the criteria to be
removed from the resource list, and calls to <f AddTrackedItem> for them to fail. This
can be used to improve the efficiency and memory usage of the resource tracker by keeping
the number of resources being tracked to a minimum. For example of you want to track
all resource types except for type 3, you can specify the FILTER_TYPEDEFAULTON and
the FILTER_TYPEOFF flags with 3 as dwTypeID. Similarly if you want to track only resource
type 7, you can specify the FILTER_TYPEDEFAULTOFF and FILTER_TYPEON flags with 7 as the
dwTypeID. Currently process filters are only installable for a single process id.
@xref <f RegisterTrackedItem> <f AddTrackedItem> <f PrintTrackedItem> <f DeleteTrackedItem> <f TrackerCallBack>
*/
VOID SC_FilterTrackedItem(DWORD dwFlags, DWORD dwType, DWORD dwProcID)
{
#ifdef MEMTRACKING
int i;
pTrack_Node pnCur, pnFree;
if (!pTOC->ulTrackingLen || !pTOC->ulTrackingStart)
{
ERRORMSG(1, (L"No resource tracking memory!!\r\n"));
return;
}
EnterCriticalSection(&Trackcs);
if (dwFlags&FILTER_TYPEDEFAULTOFF) {
lpFilterInfo->dwFlags |= FILTER_TYPEDEFAULTOFF;
for (i=0; i<MAX_REGTYPES && rgRegTypes[i].dwFlags®TYPE_INUSE; i++) {
rgRegTypes[i].dwFlags |= REGTYPE_MASKED;
}
} else if (dwFlags&FILTER_TYPEDEFAULTON) {
lpFilterInfo->dwFlags &= ~FILTER_TYPEDEFAULTOFF;
for (i=0; i<MAX_REGTYPES && rgRegTypes[i].dwFlags®TYPE_INUSE; i++) {
rgRegTypes[i].dwFlags &= ~REGTYPE_MASKED;
}
}
if (dwFlags&FILTER_TYPEON) {
if (dwType<MAX_REGTYPES && rgRegTypes[dwType].dwFlags®TYPE_INUSE) {
rgRegTypes[dwType].dwFlags &= ~REGTYPE_MASKED;
}
} else if (dwFlags&FILTER_TYPEOFF) {
if (dwType<MAX_REGTYPES && rgRegTypes[dwType].dwFlags®TYPE_INUSE) {
rgRegTypes[dwType].dwFlags |= REGTYPE_MASKED;
}
}
if (dwFlags&FILTER_PROCIDON) {
lpFilterInfo->dwFlags |= FILTER_PROCIDON;
lpFilterInfo->dwProcID = dwProcID;
} else if (dwFlags&FILTER_PROCIDOFF) {
lpFilterInfo->dwFlags &= ~FILTER_PROCIDON;
}
// now put all existing entries through the filter
for (pnCur = pnFirst; pnCur;) {
// do all the filtering
if ( (rgRegTypes[pnCur->dwType].dwFlags®TYPE_MASKED) ||
((lpFilterInfo->dwFlags&FILTER_PROCIDON)&&(lpFilterInfo->dwProcID!=pnCur->dwProcID))) {
// free the node
pnFree=pnCur;
pnCur=pnCur->pnNext;
MEMTR_deletenode(pnFree);
} else {
pnCur=pnCur->pnNext;
}
}
LeaveCriticalSection(&Trackcs);
#endif
}
/*
@func BOOL | AddTrackedItem | Registers a resource item
@parm DWORD | dwType | TypeID for the resource. Must have been got from a call
to <f RegisterTrackedItem>
@parm HANDLE | handle | Handle for the resource. Must be unique within this type.
@parm TRACKER_CALLBACK | cb | Callback function to pretty print the item. Can be NULL
if no special printing of the custom DWORDs is required. See <f TrackerCallBack>.
@parm DWORD | dwProcID | The ProcID of the process to which this resource should be
registered to. This must have been got back from a call to <f GetCurrentProcessId>
or <f GetCallerProcessId>
@parm DWORD | dwSize | Amount of RAM this resource uses
@parm DWORD | dwCustom1 | Custom dword - this is not interpreted at all. It can be used
to point at other information which is dereferenced in the callback function. If the
callback function is NULL these are simply printed out as DWORD's
@parm DWORD | dwCustom2 | Second custom dword
@rdesc TRUE if the item was added, FALSE otherwise. Function can fail if some parameter
is invalid, if the system is out of memory for resource tracking, or if the user
has filtered this resouce out.
@xref <f RegisterTrackedItem> <f DeleteTrackedItem> <f PrintTrackedItem> <f FilterTrackedItem> <f TrackerCallBack>
*/
BOOL SC_AddTrackedItem(DWORD dwType, HANDLE handle, TRACKER_CALLBACK cb, DWORD dwProcID,
DWORD dwSize, DWORD dw1, DWORD dw2)
{
#ifdef MEMTRACKING
UINT uiHashVal, uiRealHash;
EnterCriticalSection(&Trackcs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -