⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memtrk.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 3 页
字号:
/*		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&REGTYPE_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&REGTYPE_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&REGTYPE_INUSE; i++) {
	        rgRegTypes[i].dwFlags &= ~REGTYPE_MASKED;
	    }
	} 
	if (dwFlags&FILTER_TYPEON) {
	    if (dwType<MAX_REGTYPES && rgRegTypes[dwType].dwFlags&REGTYPE_INUSE) {
	        rgRegTypes[dwType].dwFlags &= ~REGTYPE_MASKED;
	    }    
	} else if (dwFlags&FILTER_TYPEOFF) {
	    if (dwType<MAX_REGTYPES && rgRegTypes[dwType].dwFlags&REGTYPE_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&REGTYPE_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 + -