Tuesday, January 25, 2011

LeakMon - Track Handle leak, GDI leak and Memory leak in your applications

LeakMon is a light weight resource leak tracking utility which can track Memory leaks, GDI object leaks and handle leaks of a process. This tool is suitable mainly for tracking down the leaks that happens in between an operation.

Downloads
LeakMon

[Download from Codeproject]
LeakMon

Prerequisite

• You need to have installed VS2010 or Microsoft Visual C++ 2010 Redistributable Package.

Visual C++ 2010 Redistributable Package can be downloaded from the below path

For 32 bit applications (4.8 MB)

http://www.microsoft.com/downloads/en/details.aspx?familyid=A7B7A05E-6DE6-4D3A-A423-37BF0912DB84&displaylang=en

For 64 bit application (5.5 MB)
http://www.microsoft.com/downloads/en/details.aspx?familyid=BD512D9E-43C8-4655-81BF-9350143D5867&displaylang=en

How to use

This tool consists of three binaries, Injector, HookDll and a DumpViewer.
To start with, run the Injector.exe.



• Refresh :- Refresh the process list
• Inject :- Injects the hook DLL to the target process to start tracking of the leak
• Dump : - Dumps the leak found so far to a file.
• Reset: :- Ignore/Clear all the leaks found up to this point.
• PDB Info : - After Injecting the DLL to the target process, you can click this button to view and make sure that all the pdb’s of necessary DLL’s are loaded correctly.

Using the injector.exe, select the target process that you want to debug. In this case say "MultiThread.exe". Now to start tracking, click the “Inject” button. On doing this, a settings window as in the below figure will pop up. (Note: The settings window is actually shown in the target process' context).



The setting window allows you to choose the “type of leak” you want to track. The types include memory leak, GDI leak and Handle leak.

The next option in the Settings dialog is “Stack Depth”. The value in the stack depth controls the number of functions that will be retrieved while tracking the allocation call stack. The value you enter in here can considerably affect the speed of the application. Lesser the value, the faster the application will be.

Collecting the call stack will never be perfect, without proper PDB files. So to get proper call stack information, specify the path PDB files of the binaries used in your application. Without the pdb’s of Microsoft dll’s such as MSVCRT.dll, MFCxx.dll etc, you will not be able to see the call stack of memory allocated using new and new[] sometimes. If you don’t have the symbols for Microsoft dlls, click on the “Add Symbol server”. Also it is a must that you have to specify the Folder in which the LeakMon binary resides. (“T:\LeakMon” in the below sample). Once you have set all the necessary pdb’s path click OK. The tracking starts from this moment

So now, once you have finished your processing and want to see all the allocations that haven’t de-allocated, press the “Dump” button in the injector. If there is some leak, it will prompt you with a save dialog, though which you can save the leak information file.

Analyzing the leak dump file


I will explain the format of the dump file with the following example. Consider the below code


i.e. The sequence of calling is in the order


CMulitThreadDlg::OnBnClickedButton1()->func1()->func2().

Now the information regarding the memory leak in the above code will look as follows.


-->Bytes allocated -- 76

_heap_alloc_base f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c(105)
_heap_alloc_dbg_impl f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(427)
_nh_malloc_dbg_impl f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(239)
_nh_malloc_dbg f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(296)
_malloc_dbg f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(160)
operator new f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(407)
operator new[] f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(442)
operator new[] f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(67)
func2 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(178)
func1 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(184)
CMulitThreadDlg::OnBnClickedButton1 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(189)
_AfxDispatchCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp(82)
CCmdTarget::OnCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp(381)
CDialog::OnCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp(85)
CWnd::OnCommand f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(2364)
CWnd::OnWndMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(1769)
CWnd::WindowProc f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(1755)
Starting from the top function, traverse down, until you find a function from your file. In the above case, func2().  So it can be concluded that, some memory that has allocated from the func2() haven’t de-allocated.

Analyzing the leak with DumpViewer

Even though you can viewer the dump file in any text editor, DumpViewer provides you some extra features that are really handy. Most of the features are self explanatory. One of the main feature is that, when you double click on a particular function in the tree, it will open the source file in visual studio with the line in which leak occurred as selected.


Under the Hood

This application basically works by hooking all the possible functions that allocates and de allocates a resource. For example when tracking memory leak it hooks the memory allocation API's such as HeapAlloc, HeapFree, VirtualAlloc, VirtualFree etc. A more detailed step by step explanation of this tool will be posted in next posts.

I have tried my best to remove the bugs in this application. But still if you encounter any bugs, let me know. Suggestions or improvements are highly appreciated.

[Update] :- Part 2  Leakmon- Under the hood

Tuesday, October 20, 2009

Dependency Checker

This is a simple light weight utility to find which all dll/exe/ocx in a folder uses a particular dll.
Download
Source File(DependsChecker_Src.zip)
Execuatble(DependsChecker_bin.zip)

My development environment usually includes large number of binaries. And I was working in some core library module which is used by many other dlls. So whenever I change something in the header file of this code library, I have to rebuild all the dependent libraries. Rebuilding the entire environment was not practical all times. So I had to create such an utility so that I can find out who all uses this code library and can rebuild those modules only.

How to Use

  1. In the “Dll Name” edit box, enter the name of the dll for which we have to search for.
  2. In the “Path” edit box, enter the folder in which we have to search for dlls/exe/ocx that uses dll entered in the “Dll Name” edit box.
  3. Click “Start” button.

Upon clicking the Start button, the list control starts’ populating the Dll, OCX and EXE’s that uses the specified dll. Please note that this application will not list dynamic dependencies and so we cannot enter ocx or COM dll as “Dll Name”.

How it works

When the start button is clicked, the application loop through each Dll, OCX and EXE’s in the specified folder. It opens each binary, parse the PE (Portable Executable) file format.
For example consider that user32.dll is specified in the "Dll name" edit box and the path is "c:\windows\system32". When user clicks on the “start” button, the application took a loop to find EXEs, dll's and OCXs in the specified folder. Intitally it enumarets all the EXEs. Suppose we got "calc.exe" as file name. The next thing to do is to map the binary file to memory. This is performed with the help of CreateFileMapping() and MapViewOfFile() function.


CFile fl;
if( !fl.Open( csExeName, CFile::modeReadCFile::shareDenyNone, 0 ))
{
CString csMsg;
csMsg.Format( _T(" Failed to open file %s"), csExeName );
AfxMessageBox( csMsg );
continue;
}
HANDLE hSM = CreateFileMapping( (HANDLE)fl.m_hFile, 0,PAGE_READONLY,0,0, _T("some_sM"));
LPVOID pBinary = MapViewOfFile( hSM,FILE_MAP_READ,0,0, fl.GetLength());
if( CheckForDependecy( csDllName, pBinary ))
{
m_List.InsertItem( 0, fl.GetFileName() );
}
UnmapViewOfFile( pBinary );
CloseHandle( hSM );
fl.Close();

As you can see in the above code, after the binary is loaded to the memory, the memory address is passed to the CheckForDependecy() function. The function cast the memory address to a IMAGE_DOS_HEADER pointer.
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) lpStartAddress;
After this, it will try to get the IMAGE_NT_HEADERS from pDOSHeader. Usually the 16 bit binaries will not be having this header. So we will ignore such binaries at this point.


// Get the PE header.
PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
if( IsBadReadPtr( pNTHeader, sizeof( IMAGE_NT_HEADERS)))
{
return false;
};

May be because of the property of data in the file, it may occur that the pNTHeader points to a valid memory. So we will add one more checking to confirm that we are dealing with PE file (The famous DRWATSON.EXE fails at this checking!!!ya it is not a PE file).


char* pSig = (char*)&pNTHeader->Signature;
if( pSig[0] != 'P' pSig[1] != 'E')
{
return false;
}

The next task is to find the IMAGE_IMPORT_DESCRIPTOR. The IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]. VirtualAddress holds the relative address of IMAGE_IMPORT_DESCRIPTOR from the starting of the memory. We can use the ImageRvaToVa() API to convert the relative adress to virtual address. There's one IMAGE_IMPORT_DESCRIPTOR for each imported executable. So we will loop through each item and check whether it is for importing the specified dll (“user32.dll” in our case )



PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageRvaToVa( pNTHeader, lpStartAddress, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
VirtualAddress, 0 );
while( pImportDesc && pImportDesc->Name )
{
// pImportDesc->Name holds the name of the import library
PVOID pName = ImageRvaToVa( pNTHeader, lpStartAddress, pImportDesc->Name , 0 );
PSTR szCurrMod = (PSTR)pName;
if( IsBadReadPtr( szCurrMod, 1 ))
{
continue;
}
CString cs = szCurrMod;
if( 0 == cs.CollateNoCase( csDllName ))
{
// everything pass. We have found one dependency
return true;
}
// Move to the next import library
pImportDesc++;
}

And for the records, let me say that, there are 1111 files in my system32 folder that has dependency with the user32.dll( Vista SP1 ).

Saturday, April 18, 2009

Centralizing modeless child dialog

Normally when we call the DoModal() function of a dialog, the dialog will created and displayed at the center of the parent dialog.



But when a modless dialog is displayed, the child dialog will be displayed at the top left portion of the parent dialog.



I noticed this when a codeproject user asked how to centralize a modeless child dialog. Initially I thought that MFC might be doing some thing in the DoModal() function. So I stepped into the DoModal() function. But I couldn't find any difference in the dialog creation in CDialog::DoModal and CDialog::Create().
Another difference that I know between a modal and modeless dialog is that, in the case of the modal dialog, the parent window will be disabled. MFC does this inside the DoModal() function. To try my luck I disabled the parent window before calling the Create function of dialog. Surprisingly it worked! The modeless child dialog came at the center of parent dialog.

So if you want to centralize a modeless dialog, just disable the parent dialog before create and re-enable it after the creation.
void CDialogBased2Dlg::OnBnClickedButton1()
{
EnableWindow( FALSE );
m_ChildDlg.Create( ChildDialog::IDD, this );
EnableWindow( TRUE );
m_ChildDlg.ShowWindow( SW_SHOW );
}

Saturday, December 20, 2008

Function to get the local system Administrator Name

A codeproject poster asked this question. He was already aware of the NetLocalGroupGetMembers function with which, was can the list of users in any groups in the system. How were he wasn't quite sure how to use it and there wasn't any sample code in the internet. So I wrote a sample and posted in codeproject and here is the copy of it.
LPLOCALGROUP_MEMBERS_INFO_1  pstMembersInfo = 0;
DWORD entriesread = 0;
DWORD totalentries = 0;
if( 0 != NetLocalGroupGetMembers( NULL, _T("Administrators"), 1, (LPBYTE*)
&pstMembersInfo,MAX_PREFERRED_LENGTH,
&entriesread, &totalentries, 0 ))
{
AfxMessageBox( _T("NetLocalGroupGetMembers failed !"));
return ;
}
for( DWORD dwIdx =0; dwIdx < entriesread; dwIdx ++ )
{
AfxMessageBox( pstMembersInfo[dwIdx].lgrmi1_name );
}
NetApiBufferFree( pstMembersInfo );

Monday, October 27, 2008

How to find whether the parent process is GUI or Console

This is not 100% fool proof. How ever in normal cases, this works great. This technique can be used to find out, whether the child application was launched from a GUI application or from a Console application.

if( AttachConsole( ATTACH_PARENT_PROCESS ))
{
AfxMessageBox( _T("Parent process is a console application"));
}
else
{
AfxMessageBox( _T("Parent process is not a console application"));
}

Tuesday, August 26, 2008

new with empty bracket

Have you ever wrote a statement like..

int *pnValue = new int[];

One of my friend asked me what will happen if the above statement is executed. Executed ??? I though the code won't even compile. Surprisingly it compile and even returned a pointer. Wow that was some thing unbelievable.

OK now the question is, what will be size of memory that pnValue points?

The two API's in windows that allocates and de allocates the memeory are HeapAlloc and HeepFree. The CRT functions malloc and free are actually wrappers the above API. The new, new[], delete, delete[] are again another wrapper around the malloc and free. So when ever you allocates some memory using new or new[], it will finally reach the HeapAlloc function. This function is defined as

LPVOID WINAPI HeapAlloc(
__in HANDLE hHeap,
__in DWORD dwFlags,
__in SIZE_T dwBytes
);


From the above definition, you can see that the third parameter to this function is the number of BYTES to be allocated . So to find out what "new int[]" returns, we can put a break point in the entry point of HeapAlloc and check the value of dwBytes( in dis assembly ).

when I tried, the dwBytes turned out be 1 !!! This one byte cannot even hold one int variable. That means any further operation using such a pointer will possibly crash.

Another interesting thing is "int *pnValue = new int[0];" also returns a pointer pointing a memory of 1 byte long.

Wednesday, August 20, 2008

How to open Popup Blocker Settings window of IE programmatically

How to open Popup Blocker Settings window of IE programmatically??

Well it is with the help of "DisplayPopupWindowManagementDialog" function in the "C:\WINDOWS\system32\inetcpl.cpl".

But here rather just showing a misterious function, I would like to explain the methods by which I found out the name of function.

This question was asked by some one in the codeproject and at that time I was also unaware of any function for this. How ever I felt it interesting so just decided to have a try.

At first I took this "Popup Blocker Settings " dialog in the IE. My first intention was to find out the dll name which created the dialog. There is an application called WinID[^] with which we can find which dll created a perticular windows. In one of my previous post, I have explained How to find which dll / exe created a window.[^] using code. Below is a screenshot of what WinID showed me for the "Popup Blocker Settings" dialog .



It told me that "USER32.dll" has created the dialog. Liar... I was much sure that user32.dll isn't the real dll behind it. So this technique to find the dll didn't really work. So I had to find another way...

Every window has a thread associated with it. If you have the window handle, you can easily retirive the thread Id associated with it using the GetWindowThreadProcessId function. Any way I am not going to code for this. Tools like spy++, WinID displays the thread id of the window if we select a window using it. So the Thread ID displayed in Spy++ was 0xB94( 2964 in decimal ).

If we took the properties of a process in the process explorer, it will list all the threads in the process and each thread's call stack. So the thing next to do is to select the iexplorer process, select the thread with ID 2964 and took its call stack.



And in the call stack, there was only one un familiar dll and function the "inetcpl.cpl" and the DisplayPopupWindowManagementDialog function in it. So I found out the "inetcpl.cpl" file in the system32 folder and when double clicked on it, huiii it shows the "internet options" dialog.

The control panel files (.cpl ), are just a dll with a some special export functions( If you want to know more about control panel files I suggest you to read Paul DiLascia's Q&A[^] article ). With the dependency walker, I confirmed the presence of DisplayPopupWindowManagementDialog in it. But to call this function, I need to the find how it is declared, what all are the arguments etc. Fortunately some else has already document the function proto and with a google search, I was able to find it out. Happy ending!!!!

And ho ya here is the sample code..

typedef BOOL (WINAPI *DisplayPopupWindowP)( HANDLE hWnd, LPCTSTR lpCaption );
void CDialogBasedDlg::OnBnClickedButton1()
{
HMODULE hModule = LoadLibrary( _T("inetcpl.cpl") );
DisplayPopupWindowP DisplayPopupWindowManagementDialog =
( DisplayPopupWindowP)GetProcAddress(hModule,
"DisplayPopupWindowManagementDialog" );
if( !DisplayPopupWindowManagementDialog )
{
return;//error
}
DisplayPopupWindowManagementDialog( m_hWnd,
_T("www.Sitetounblock.com"));
}