📄 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 MEMTRACKINGCALLBACKINFO cbi;pTrack_Node pnFirst; // index of first add in sequencepTrack_Node pnLast; // index of last add in sequenceLPMEMTR_ITEMTYPE rgRegTypes; // registered typesLPMEMTR_FILTERINFO lpFilterInfo; // filter informationpTrack_Node table; // hash tableUINT 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 IntRaPRUNTIME_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 PRPRUNTIME_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 pointersvoid 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 + -