tag:blogger.com,1999:blog-86148198325443667182024-03-14T05:48:51.844-07:00ZeroMemorySome tips, tricks and bugs in vc++Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-8614819832544366718.post-446319513280687302015-04-06T08:43:00.001-07:002016-09-20T05:53:41.157-07:00Parallelizing c++ boost unit test cases<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
<u>Downloads</u><br />
<br />
<h4>
<todo line="" opening=""><a href="https://drive.google.com/open?id=0B06l8mKxBTXCM19PYjQ2QkdSSTg&authuser=0" target="_blank">Source.zip</a></todo></h4>
<h4>
<a href="https://drive.google.com/open?id=0B06l8mKxBTXCRGhrMzR4Tl91eVE&authuser=0" target="_blank">SampleApplication.zip</a> ( Please update the boost include and lib paths in project settings. )</h4>
<todo line="" opening=""><u>Alternate Download link</u></todo><br />
<todo line="" opening=""><br /></todo>
<todo line="" opening=""><a href="http://www.codeproject.com/KB/cpp/894186/SampleApplicaiton.zip">SampleApplicaiton.zip</a></todo><br />
<a href="http://www.codeproject.com/KB/cpp/894186/Source.zip">Source.zip</a><br />
<todo line="" opening=""><br /></todo>
<todo line="" opening="">In big projects, it is common to have thousands of unit test cases. In one of our projects we used boost framework for writing unit TCs and used to run all the TCs in build server after every check-in. The number of TCs eventually grew to thousands and it takes around 3, 4 hours to finish all the test cases. Even though our build server was running on a 32 core machine, we couldn't take advantage of it because boost's framework always run test cases in one thread. Running in multiple thread is not a generic solution as the testcases might be accessing some shared object that could cause synchronization issues. There is one alternate solution available via CMake which is describe in the post <a href="http://baptiste-wicht.com/posts/2012/10/run-boost-test-parallel-cmake.html" target="_blank">Run your Boost Tests in parallel with CMake</a> . The only down side of this solution is that, you have to list down each testcase of your unit test application in the makefile. When we have thousands of test cases, it is not a very feasible solution. Then we started looked into the boost test framework and see if anything cane be done at the framework side.</todo></div>
<h4 style="text-align: left;">
<u>Tweeking startup code</u></h4>
<div style="text-align: justify;">
</div>
<ul>
<li>Supported OS: Windows and Unix - compatible OS</li>
<li>Tested on boost 1.47</li>
</ul>
<span style="text-align: justify;">This solution actually works with a slight modification in main function of boost test case. All you have to do is to include unit_test_main_parallel.hpp </span><todo -="" insert="" link="" style="text-align: justify;"> instead of boost/test/unit_test.hpp in your unit test case project.After building your unitestcase application, to run the testcases in parallel simply add the option "--dist_tc=<no of="" parallel="" run="" test="" to="">"</no></todo><br />
<br />
For eg:<br />
<blockquote class="tr_bq">
<span style="color: #b45f06;">c:\Naveen\tmp>UnitTestApp.exe --dist_tc=5</span></blockquote>
The above command will start one parent UnitTestApp.exe and 5 child UnitTestApp.exe , each executing one test case at a time. Here is how it looks in process explorer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBYizok0sC_SGZTEqVWhZW2YHpoPEHiLWWhbXZGYCyNbOkLSJlgP9PloVVgr802ef4kFh2kW_tD9gDsEQpftV9BxITw8yW56qP-i4uQxqrC-bx9T0LbAry5Wta7bcEEPgj0nY4AoIfmiQ/s1600/tc_parallel.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBYizok0sC_SGZTEqVWhZW2YHpoPEHiLWWhbXZGYCyNbOkLSJlgP9PloVVgr802ef4kFh2kW_tD9gDsEQpftV9BxITw8yW56qP-i4uQxqrC-bx9T0LbAry5Wta7bcEEPgj0nY4AoIfmiQ/s1600/tc_parallel.JPG" /></a></div>
<br />
Once a child application finishes the unit test case assigned to it, the child process exit by itself and another child application is spooled by the parent to execute the next TC. Please note that this option is incompatible with --run_test option. if --run_test is specified, --dist_tc option will be ignored.<br />
<h4 style="text-align: left;">
<u>Under the Hood</u></h4>
<div>
Underlying implementation is actually quite simple. </div>
<div>
<ol style="text-align: left;">
<li>When application starts, it traverse though all test case in the application and create a list of test cases. </li>
<li>For each test case in the list, invoke child process with an additional --run_test option specifying the test case name.</li>
<li>Redirect the console output of child process back to the parent application and print it.</li>
</ol>
</div>
<div>
<h4 style="text-align: left;">
<u>Files</u></h4>
There are 3 files in this source<br />
<ul style="text-align: left;">
<li>unit_test_main_parallel.hpp - Main header file that you need to include.</li>
<li>unit_test_main_unix.ipp - unix specific code.</li>
<li>unit_test_main_win.ipp - windows specific code.</li>
</ul>
<br />
Since Windows doesn't support POSIX API's, I had to write separate implementation for windows OS's. The unit_test_main_parallel.hpp will choose one of the .ipp file depending the platform in which it is getting compiled.<br />
<br />
<br /></div>
</div>
Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-34142957020384714862011-05-23T07:32:00.000-07:002011-05-23T07:32:56.420-07:00LeakMon :- Part 3 Opening a file in visual studio through automation<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">This is the 3rd post related to the <a href="http://0memory.blogspot.com/2011/01/leakmon-track-handle-leak-gdi-leak-and.html">LeakMon</a> tool. In this post we will see how the DumpViewer( DumpViewer is an application used to analyze the leak dump created by LeakMon ) is able to open a perticular file in Visual Studio and highlight the specified line.</div><br />
<strong>Step 1:- Finding out the version of Visual studio to use</strong><br />
It is 2011 now and we have Visual studio 2010. But there are peoples or companies who still use Visual Studio 6. Things have changed a lot from Visual Studio 6 to Visual Studion 10, even the EXE name has changed. So the first task is to find out which verion of Visual Studio to use.<br />
<br />
<div style="text-align: justify;">DumpViewer uses the same Visual Studio version that is reigstered as the default program for documents such as .c, .cpp, .h, .hpp in your machine. For instance, say we have the following line shown in DumpViewer..</div><div style="text-align: justify;"><span style="color: #b45f06;">func2 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(178)</span></div><div style="text-align: justify;"></div><div style="text-align: justify;">DumpViewer will extract the file path and line number, from the above line and pass it to the <a href="http://msdn.microsoft.com/en-us/library/bb776419(v=vs.85).aspx">FindExecutable</a> function. This function will return the path of executable that is registered for above file types, which will be usually Visual Studio. If it is not Visual Studio, sorry it will fail! <br />
<br />
In the file name of the executable returned by <a href="http://msdn.microsoft.com/en-us/library/bb776419(v=vs.85).aspx">FindExecutable</a> function, we will check there is a string "msdev.exe" or "devenv.exe" in it. If there is "msdev.exe" in the string, code that does the automation of Visual Studio 6 is called or otherwise the code to handle higher version of Visual Studio.</div><pre><span style="color: #b45f06;">const LPCTSTR VC_6_APP_NAME = _T("msdev.exe");
const LPCTSTR VC_8_APP_NAME = _T("devenv.exe");
if( 0 == csExe.CompareNoCase( VC_6_APP_NAME ))
{
// launch vc6
OpenUsingVS<IApplication>( IID_IDispatch, L"MSDEV.Application",csFileName_i, nLineNo );
}
else if( 0 == csExe.CompareNoCase( VC_8_APP_NAME ) )
{
// launch vs7 or any other higher versions of VS
OpenUsingVS<_DTE>( EnvDTE::IID__DTE,
L"VisualStudio.DTE",csFileName_i, nLineNo );
}</span>
</pre><br />
<strong>Step 2:- Getting a pointer to already running instance of VisualStudio</strong><br />
<div style="text-align: justify;">Since we are going to open a file through auotmation, we need a pointer of either IApplication or _DTE (IApplication for Visual Studio 6 and _DTE for Visual Studio 7 and higher ) . We can create and instance of above type using the CoCreateInstance by passing the IID and CLSID. But this will create a new instance of VisualStudio each time we try to open a new file. So what we want is to get a pointer to IApplication / _DTE of an already running instance of Visual Studio if any. This can be done by enumerating the Moniker in the ROT (Running Object Table).</div><div align="left" style="height: 263px; margin: 20px auto; overflow: auto;"><pre><span style="color: #b45f06;">
template<class T>
bool OpenUsingVS( IID riid, CString csProgID, CString csFileName_i, int nLineNo)
{
HRESULT hRes;
CLSID clsid;
CComPtr<IUnknown> punk;
CComPtr<T> dte;
RETURN_ON_FAIL( ::CLSIDFromProgID( csProgID.operator LPCTSTR(), &clsid) );
// Search through the Running Object Table for an instance of Visual Studio
// to use that either has the correct solution already open or does not have
// any solution open.
CComPtr<IRunningObjectTable> ROT;
RETURN_ON_FAIL( GetRunningObjectTable( 0, &ROT ) );
CComPtr<IBindCtx> bindCtx;
RETURN_ON_FAIL( CreateBindCtx( 0, &bindCtx ) );
CComPtr<IEnumMoniker> enumMoniker;
RETURN_ON_FAIL( ROT->EnumRunning( &enumMoniker ) );
CComPtr<IMoniker> dteMoniker;
RETURN_ON_FAIL( CreateClassMoniker( clsid, &dteMoniker ) );
CComPtr<IMoniker> moniker;
CComPtr<IMoniker> moniker2;
ULONG monikersFetched = 0;
while ( enumMoniker->Next( 1, &moniker, &monikersFetched ) == S_OK)
{
moniker2 =NULL;
moniker->Reduce( bindCtx, MKRREDUCE_ALL, NULL, &moniker2 );
IMoniker* pMon = (0 != moniker2)?moniker2:moniker;
if ( moniker2->IsEqual( dteMoniker ) )
{
hRes = ROT->GetObject( moniker, &punk );
if ( hRes == S_OK )
{
dte = punk;
if ( dte )
{
// We have got an instance pointer. Lets try to open
// the file using that pointer
if( OpenFile( dte,csFileName_i, nLineNo ))
return true;
dte = 0;
}
}
punk = NULL;
}
moniker = NULL;
}
if ( !dte )
{
// we didnt get any pointer from ROT. So lets go an create and new
// instance.
RETURN_ON_FAIL( ::CoCreateInstance( clsid, NULL, CLSCTX_LOCAL_SERVER, riid , (LPVOID*)&punk ) );
dte = punk;
if ( !dte )
return false;
OnLaunch( dte );
OpenFile( dte,csFileName_i, nLineNo );
}
return true;
}
</span></pre></div><br />
As you can in the above code, if we failed to get a vaild instance pointer of Visual Studio, we create a new one using CoCreateInstance. In Visual Studio 7 and higher, as soon as we release the com pointer that we got from CoCreateInstance, Visual Studio will terminate. To prevent Visual Studio from exiting like this, we need to call <span style="color: #b45f06;">put_UserControl</span> of <span style="color: #b45f06;">DTE</span> interface.<br />
<br />
<strong>Step 3 Opening a File and selecting a line of it</strong><br />
From this part on, the processing is different for Visual Studio 6 and other versions of Visual Studio.<br />
<br />
<strong>In Visual Studio 6</strong><br />
<div align="left" style="height: 263px; margin: 20px auto; overflow: auto;"><pre><span style="color: #b45f06;">
#define dsWindowStateMaximized 1
bool OpenFile(IApplication* m_spApplication,CString csFileName_i, int nLineNo )
{
CComPtr<IDispatch> pDispatch;
// Make it visible just in case if it is not
m_spApplication->put_Visible( VARIANT_TRUE );
// Maximize the window
m_spApplication->put_WindowState( dsWindowStateMaximized );
// Get a pointer to the IDocument interface
m_spApplication->get_Documents( &pDispatch );
CComQIPtr<IDocuments> pDocs = pDispatch;
CComVariant type="Auto";
CComVariant read="False";
pDispatch = 0;
// The Open function of IDocument opens the file.
pDocs->Open( CComBSTR(csFileName_i),type, read, &pDispatch );
// Now for selecting a line, we need to get pointer to ITextSelection
// Interface
CComQIPtr<ITextDocument> pDoc = pDispatch;
pDispatch = 0;
pDoc->get_Selection( &pDispatch );
CComQIPtr <ITextSelection> pTextSelection = pDispatch;
CComVariant varReserved( FALSE );
// now just set the cursor to the correct line and call SelectLine of ITextSelection
pTextSelection->StartOfDocument( varReserved );
pTextSelection->LineDown( varReserved, CComVariant(nLineNo-1));
Sleep( 1000 );
pTextSelection->SelectLine();
return true;
}
</span></pre></div><br />
<strong>In Visual Studio 7 and higher</strong><br />
<div align="left" style="height: 263px; margin: 20px auto; overflow: auto;"><pre><span style="color: #b45f06;">
bool OpenFile( _DTE* pDTE,CString csFileName_i, int nLineNo )
{
HRESULT hRes = 0;
CComPtr<ItemOperations> Operations;
// Get the ItemOperations pointer
RETURN_ON_FAIL(pDTE->get_ItemOperations( &Operations ));
CComPtr<Window> Wnd;
// Open the file using ItemOperations pointer
RETURN_ON_FAIL(Operations->OpenFile( CComBSTR( csFileName_i),
CComBSTR(vsViewKindTextView), &Wnd ))
// It might take some time to open the file.
// so we will wait in a loop
CComPtr<Document> pDoc;
for( int nIdx =0; nIdx < 5; nIdx ++ )
{
pDTE->get_ActiveDocument( &pDoc );
//Sleep( 100 );
if( pDoc )
{
break;
}
if( nIdx == 4 )
{
return false;
}
Sleep( 100 );
}
// Active the main window.
CComPtr<Window> pMainWnd;
RETURN_ON_FAIL(pDTE->get_MainWindow( &pMainWnd ))
pMainWnd->Activate();
// Get the TextSelection pointer
CComPtr<IDispatch> pDisp = 0;
RETURN_ON_FAIL(pDoc->get_Selection( &pDisp ));
CComQIPtr<TextSelection> pSelection = pDisp;
//GotoLine with VARIANT_TRUE will make the line selected
pSelection->GotoLine( nLineNo, VARIANT_TRUE);
return true;
}
</span></pre></div></div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com5tag:blogger.com,1999:blog-8614819832544366718.post-50746678228515811592011-03-30T23:09:00.000-07:002011-03-31T22:37:54.877-07:00LeakMon :- Part 2 Under the hood<div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" style="text-align: left;" trbidi="on">This post explains how <a href="http://0memory.blogspot.com/2011/01/leakmon-track-handle-leak-gdi-leak-and.html">LeakMon</a> application tracks various kind of resource allocation and report them.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
<strong>Download Source :- </strong><a href="https://docs.google.com/leaf?id=0B06l8mKxBTXCNjI1NDJlNDItMGRkNC00Mzg4LWE4YzQtZTQ4ZTU3OTIyMTU1&hl=en">LeakMon_source.zip</a></div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
<strong>Basic working principle</strong></div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">Consider the case of tracking memory allocation. In this case, Leakmon will hook all the possible memory allocation and de-allocation functions. So when ever a function allocates some memory it will keep the pointer to the newly allocated memory as a key in a map and the call stack as value. If this memory is de-allocated, this entry in the map is removed. So at any point all the entries in the map are those memory pointers which haven't de-allocted. When you ask the Leakmon to Dump the leak, all it does is dumping the entries in the map.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">This application has the following distinguishing features from the other resource leak tracking applications in codeproject and around.</div><div dir="ltr" style="text-align: justify;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">1. You dont have to modify any single line of code to start tracking</div><div dir="ltr" style="text-align: justify;" trbidi="on">2. It will track the allocation from all the binaries in the process. Means the tracking is not restricted to only the EXE binary of the process. It will track allocation from all the dependent DLL's as well</div><div dir="ltr" style="text-align: justify;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">OK, Let's start with the working of LeakMon from the first binary, Injector.exe</div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: left;" trbidi="on"><strong>Injector application</strong></div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
</div><div class="separator" dir="ltr" style="clear: both; text-align: center;" trbidi="on"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp6CPgv6ECvGbn6Bx0E5RQqbw0wH8z2gLpoofBPO2FKx6v9b7bxIzRsIzx3mRsESxm-ybTFjaYTbCBUtQ5nb4533ICXfUDVOMmVBuivoi_mAhijAT7FSdllOCKq0wzTdqBs8_M8fmmh_Q/s1600/Injector.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp6CPgv6ECvGbn6Bx0E5RQqbw0wH8z2gLpoofBPO2FKx6v9b7bxIzRsIzx3mRsESxm-ybTFjaYTbCBUtQ5nb4533ICXfUDVOMmVBuivoi_mAhijAT7FSdllOCKq0wzTdqBs8_M8fmmh_Q/s400/Injector.JPG" width="400" /></a></div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">The Injector.exe allows you to select the process of which you want to track leak. It will list all the process in the system with the help of CreateToolhelp32Snapshot, Process32First and Process32Next functions.</div><div dir="ltr" style="text-align: justify;" trbidi="on"><br />
So, when if you select a process and press the "Inject" button, what it does is, It will inject the "HookDll.dll" to the traget process' address space. This is done with the help of CreateRemoteThread API. Injecting a DLL using CreateRemoteThread API is explained detailed in the article <a href="http://www.codeproject.com/KB/threads/winspy.aspx">Three Ways to Inject Your Code into Another Process</a>. Anyway in Injector.exe the following code part does the injection.</div><div dir="ltr" style="text-align: left;" trbidi="on"></div><div dir="ltr" style="text-align: left;" trbidi="on"><div align="left" style="height: 263px; margin: 20px auto; overflow: auto; width: 535px;"><span style="color: #e69138;">void CInjectorDlg::OnInject() </span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;">......</span><br />
<span style="color: #e69138;">CString csPid = m_List.GetItemText( nSelected, 0 );</span><br />
<span style="color: #e69138;">DWORD dwPID = _ttoi( csPid );</span><br />
<span style="color: #e69138;">HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|</span><br />
<span style="color: #e69138;">PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ,</span><br />
<span style="color: #e69138;">FALSE, dwPID ); </span><br />
<span style="color: #e69138;">if( !hProcess)</span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;"> AfxMessageBox( _T("Failed to open the process" ));</span><br />
<span style="color: #e69138;"> return;</span><br />
<span style="color: #e69138;">}</span><br />
<span style="color: #e69138;">HINSTANCE hLib = LoadLibrary( "Kernel32.dll" ); </span><br />
<span style="color: #e69138;">PROC pLoadLib = (PROC)GetProcAddress( hLib, "LoadLibraryA" );</span><br />
<span style="color: #e69138;">void* pLibRemote = ::VirtualAllocEx( hProcess, NULL, csPath.GetLength(),</span><br />
<span style="color: #e69138;">MEM_COMMIT, PAGE_READWRITE );</span><br />
<span style="color: #e69138;">::WriteProcessMemory( hProcess, pLibRemote, (void*)csPath.operator LPCTSTR(),</span><br />
<span style="color: #e69138;">csPath.GetLength(), NULL );</span><br />
<span style="color: #e69138;">if( !CreateRemoteThread( hProcess, 0, 0, (LPTHREAD_START_ROUTINE)pLoadLib, pLibRemote, 0, 0 ))</span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;"> AfxMessageBox( "Create Remote thread Failed" );</span><br />
<span style="color: #e69138;"> :VirtualFreeEx( hProcess, pLibRemote,csPath.GetLength(), MEM_RELEASE );</span><br />
<span style="color: #e69138;">}</span><br />
<span style="color: #e69138;">}</span></div></div><div dir="ltr" style="text-align: left;" trbidi="on"><strong>The HookDll</strong></div><div dir="ltr" style="text-align: justify;" trbidi="on"><br />
</div><div dir="ltr" style="text-align: justify;" trbidi="on">HookDll.dll is the core part of the LeakMon. It performs almost all of the resource tracking stuffs. HookDll starts its working once it got injected into the target process. The BOOL CHookDllApp::InitInstance function gets called when this dll is loaded in the target process. This function however doesn't do much other than just creating a worker thread, DumpController.</div><div align="left" style="height: 116px; margin: 20px auto; overflow: auto; width: 470px;"><span style="color: #e69138;">BOOL CHookDllApp::InitInstance() </span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;"> HANDLE hThread = ::CreateThread( 0,0,DumpController, 0,0, 0 );</span><br />
<span style="color: #e69138;"> CloseHandle( hThread ); </span><br />
<span style="color: #e69138;"> return CWinApp::InitInstance();</span><br />
<span style="color: #e69138;">}</span></div>Now when the DumpController starts, it will first show the configuration dialog, where you can,<br />
1. Select what kind of resource allocation you want to track<br />
2. Select the path of the PDB's of the application<br />
3. Stack depth<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcNAQfSSQrpruXUYP4Ik5PXK0rkJuX5v0RWa2g8x1Yd0mzIYA0l3T4h9TGUmsyuQ11JYiq7JFqSqV8HLsiDDxKGW82bqIHlmlaDmAWHlfYGr0zWt1_AbMlLS_c1mVPdU50vxePVJCmqoI/s1600/SettingsDlg.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="221" r6="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcNAQfSSQrpruXUYP4Ik5PXK0rkJuX5v0RWa2g8x1Yd0mzIYA0l3T4h9TGUmsyuQ11JYiq7JFqSqV8HLsiDDxKGW82bqIHlmlaDmAWHlfYGr0zWt1_AbMlLS_c1mVPdU50vxePVJCmqoI/s400/SettingsDlg.JPG" width="400" /></a></div><br />
<div style="text-align: justify;"><strong>DebugHelp Functions</strong></div><div style="text-align: justify;">HookDll creates the call the stack, with the help of DebugHelp Functions. For the DebugHelp function to return the call stack correctly, it is necessary that you specify the correct PDB path of the application. Also it always good to use the latest version of the dbghelp.dll that comes with latest version of <em>Debugging tool for windows</em>. Another good feature that LeakMon support is integration with symbol server. However, adding the Symbol server functionality is very easy. All you have to do is to ensure that, the symsrv.dll is present in the same directory from where dbghelp.dll is loaded.</div><div style="text-align: justify;">So now once you click the OK button, in the config dialog, the HookDll will start initializing symbol handler. To initialize symbol handler we have to call SymInitialize. When you call SymInitialize with the value of fInvadeProcess as TRUE, it will load symbol table for all the dlls in the process. But wait, we do better, we can show the progress of loading the symbols of each dll. Showing the progress of symbol loading is important especially when you are downloading a symbol from symbol server, which may take significant time.You might have seen this feature in Visual studio. when you start debugging an application in VS, it will show the symbol loading progress of each dll in the status bar.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnV7bezf8iVAhllRtpx11RW4uQ1pl3zBVOR-RUYN_0iQF9SlwSHCzOhdLOSbKa9GtQNDBXhyo2k3XIPRsNZZai-F9K_HH6mmnpY9Oaf9-x8PiEnrRW-zmUDaxyXMtMCTElA5vgTxWF9PU/s1600/loading+symbols.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="56" r6="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnV7bezf8iVAhllRtpx11RW4uQ1pl3zBVOR-RUYN_0iQF9SlwSHCzOhdLOSbKa9GtQNDBXhyo2k3XIPRsNZZai-F9K_HH6mmnpY9Oaf9-x8PiEnrRW-zmUDaxyXMtMCTElA5vgTxWF9PU/s640/loading+symbols.JPG" width="640" /></a></div><div style="text-align: justify;">To show the progress, we can register one call back with the function SymRegisterCallback64. Our callback function will get called before loading each symbol. </div><div></div><div align="left" style="height: 263px; margin: 20px auto; overflow: auto; width: 598px;"><span style="color: #e69138;">void ConfigDlg::OnOk() </span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;">..................</span><br />
<span style="color: #e69138;"> SymInitialize(GetCurrentProcess(), (LPTSTR)csWholePath.operator LPCTSTR() , FALSE );</span><br />
<span style="color: #e69138;"> SymRegisterCallback64( GetCurrentProcess(),SymRegisterCallbackProc64,(ULONG64 )this );</span><br />
<span style="color: #e69138;">..................</span><br />
<span style="color: #e69138;"> if( pSymRefreshModuleList )</span><br />
<span style="color: #e69138;"> {</span><br />
<span style="color: #e69138;"> pSymRefreshModuleList( GetCurrentProcess());</span><br />
<span style="color: #e69138;"> }</span><br />
<span style="color: #e69138;"> ..................</span><br />
<span style="color: #e69138;">}</span><br />
<span style="color: #e69138;"><br />
</span><br />
<span style="color: #e69138;">BOOL CALLBACK ConfigDlg::SymRegisterCallbackProc64(HANDLE hProcess,</span><br />
<span style="color: #e69138;"> ULONG ActionCode,</span><br />
<span style="color: #e69138;"> ULONG64 CallbackData,</span><br />
<span style="color: #e69138;"> ULONG64 UserContext)</span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;"> if( CBA_DEFERRED_SYMBOL_LOAD_START == ActionCode )</span><br />
<span style="color: #e69138;"> {</span><br />
<span style="color: #e69138;"> PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 pSybolLoadInfo =(PIMAGEHLP_DEFERRED_SYMBOL_LOAD64)CallbackData;</span><br />
<span style="color: #e69138;"> <span style="color: black;"> </span>ConfigDlg* pDlg = (ConfigDlg*)UserContext;</span><br />
<span style="color: #e69138;"> <span style="color: black;"> </span>CString csLoadtext = _T("Loading symbol for file: ");</span><br />
<span style="color: #e69138;"> <span style="color: black;"> </span>csLoadtext += pSybolLoadInfo->FileName;</span><br />
<span style="color: #e69138;"> <span style="color: black;"> </span>pDlg->m_ProgressDlg.SetDlgItemText( IDC_LOAD_INFO, csLoadtext );</span><br />
<span style="color: #e69138;"> }</span><br />
<span style="color: #e69138;"> // return false to indicate that we are not doing any symbol loading by ourself</span><br />
<span style="color: #e69138;"> return FALSE;</span><br />
<span style="color: #e69138;">}</span></div><strong>API Hooking</strong><br />
<br />
<div style="text-align: justify;">To intercept the allocation and de-allocation calls(functions) made by dll's, LeakMon relies on User mode API hooking though IAT patching. I am not going to explain the IAT patching because there are already several articles in codeproject and other sites having a detailed explanation. Here is one good article to start with <a href="http://www.codeproject.com/KB/system/hooksys.aspx">API hooking revealed</a>. </div><div style="text-align: justify;">How ever one thing that is different in LeakMon with usual custom is that, it doesn't walk through the dependency chain of dll. I mean, if A.exe has statically linked to B.dll and again if B.dll is linked to C.dll, what usually does for API hooking is, it will hook the API imported by A.exe, then find out the dependency of A.exe, which is B.dll, so hook its imported functions. Then it find out the depended dll of B.dll which is C.dll, hook it functions and so on. The problem with this approach is that only statically linked dlls will be hooked. If you are making some calls to a COM dll or if I you are creating an Active-X control in your application, those dll will never get hooked. So instead of walking through the dependency chain, Leakmon, enumerates all the dll's in that process and hooks it. In fact this approach is a little more easier too. It make use of the Module32First and Module32Next set of functions for this purpose.</div><br />
<div style="text-align: justify;">As you can see, this application can track three kind of resource allocation and de-allocation namely Memory, GDI objects and HANDLES. Windows have a wider set of function for allocation and de-allocation for each of of resources. The following table shows the list of API's LeakMon hooks for tracking allocations/de-allocation of resources.</div><br />
<table align="center" border="1"><tbody>
<tr><th colspan="4">Memory allocation and de-allocation functions</th></tr>
<tr><td>HeapAlloc</td><td>HeapFree</td><td>HeapReAlloc</td><td>VirtualAllocEx</td></tr>
<tr><td>VirtualFreeEx</td><td>GlobalAlloc</td><td>GlobalReAlloc</td><td>GlobalFree</td></tr>
<tr><td>LocalAlloc</td><td>LocalReAlloc</td><td>LocalFree</td><td></td></tr>
</tbody></table><br />
<table align="center" border="1"><tbody>
<tr><th colspan="3">GDI object creation and deletion functions</th></tr>
<tr><th colspan="3">Bitmaps</th></tr>
<tr><td>LoadBitmapA</td><td>LoadBitmapW</td><td>LoadImageA</td></tr>
<tr><td>LoadImageW</td><td>CreateBitmap</td><td>CreateBitmapIndirect</td></tr>
<tr><td>CreateCompatibleBitmap</td><td>CreateDIBitmap</td><td>CreateDIBSection</td></tr>
<tr><td>CreateDiscardableBitmap</td><td>CopyImage</td><td>GetIconInfo</td></tr>
<tr><td>GetIconInfoExA</td><td>GetIconInfoExW</td><td></td></tr>
<tr><th colspan="3">Icons</th></tr>
<tr><td>CopyIcon</td><td>CreateIcon</td><td>CreateIconFromResource</td></tr>
<tr><td>CreateIconFromResourceEx</td><td>CreateIconIndirect</td><td>DestroyIcon</td></tr>
<tr><td>DuplicateIcon</td><td>ExtractAssociatedIconA</td><td>ExtractAssociatedIconW</td></tr>
<tr><td>ExtractAssociatedIconExA</td><td>ExtractAssociatedIconExW</td><td>ExtractIconA</td></tr>
<tr><td>ExtractIconW</td><td>ExtractIconExA</td><td>ExtractIconExW</td></tr>
<tr><td>LoadIconA</td><td>LoadIconW</td><td>PrivateExtractIconsA</td></tr>
<tr><td>PrivateExtractIconsW</td><td></td><td></td></tr>
<tr><th colspan="3">Cursor</th></tr>
<tr><td>CreateCursor</td><td>DestroyCursor</td><td>LoadCursorA</td></tr>
<tr><td>LoadCursorW</td><td>LoadCursorFromFileA</td><td>LoadCursorFromFileW</td></tr>
<tr><th colspan="3">Brush </th></tr>
<tr><td>CreateBrushIndirect</td><td>CreateSolidBrush</td><td>CreatePatternBrush</td></tr>
<tr><td>CreateDIBPatternBrush</td><td>CreateDIBPatternBrushPt</td><td>CreateHatchBrush</td></tr>
<tr><th colspan="3">Device context </th></tr>
<tr><td>CreateCompatibleDC</td><td>CreateDCA</td><td>CreateDCW</td></tr>
<tr><td>CreateICA</td><td>CreateICW</td><td>GetDC</td></tr>
<tr><td>GetDCEx</td><td>GetWindowDC</td><td>ReleaseDC</td></tr>
<tr><td>DeleteDC</td><td></td><td></td></tr>
<tr><th colspan="3">Font </th></tr>
<tr><td>CreateFontA</td><td>CreateFontW</td><td>CreateFontIndirectA</td></tr>
<tr><td>CreateFontIndirectW</td><td></td><td></td></tr>
<tr><th colspan="3">Metafile </th></tr>
<tr><td>CreateMetaFileA</td><td>CreateMetaFileW</td><td>CreateEnhMetaFileA</td></tr>
<tr><td>CreateEnhMetaFileW</td><td>GetEnhMetaFileA</td><td>GetEnhMetaFileW</td></tr>
<tr><td>GetMetaFileA</td><td>GetMetaFileW</td><td>DeleteMetaFile</td></tr>
<tr><td>DeleteEnhMetaFile</td><td>CopyEnhMetaFileA</td><td>CopyEnhMetaFileW</td></tr>
<tr><td>CloseEnhMetaFile</td><td>CloseMetaFile</td><td></td></tr>
<tr><th colspan="3">Pen</th></tr>
<tr><td>CreatePen</td><td>CreatePenIndirect</td><td>ExtCreatePen</td></tr>
<tr><th colspan="3">Region </th></tr>
<tr><td>PathToRegion</td><td>CreateEllipticRgn</td><td>CreateEllipticRgnIndirect</td></tr>
<tr><td>CreatePolygonRgn</td><td>CreatePolyPolygonRgn</td><td>CreateRectRgn</td></tr>
<tr><td>CreateRectRgnIndirect</td><td>CreateRoundRectRgn</td><td>ExtCreateRegion</td></tr>
<tr><th colspan="3">Palette </th></tr>
<tr><td>CreateHalftonePalette</td><td>CreatePalette</td><td></td></tr>
<tr><th colspan="3">Common Function</th></tr>
<tr><td>DeleteObject</td><td></td><td></td></tr>
</tbody></table><br />
<table align="center" border="1"><tbody>
<tr><th colspan="3">Handle creation and deletion functions</th></tr>
<tr><th colspan="3">Synchronization objects</th></tr>
<tr><td>CreateEventA</td><td>CreateEventW</td><td>CreateEventExA</td></tr>
<tr><td>CreateEventExW</td><td>OpenEventA</td><td>OpenEventW</td></tr>
<tr><td>CreateMutexA</td><td>CreateMutexW</td><td>CreateMutexExA</td></tr>
<tr><td>CreateMutexExW</td><td>OpenMutexA</td><td>OpenMutexW</td></tr>
<tr><td>CreateSemaphoreA</td><td>CreateSemaphoreW</td><td>CreateSemaphoreExA</td></tr>
<tr><td>CreateSemaphoreExW</td><td>OpenSemaphoreA</td><td>OpenSemaphoreW</td></tr>
<tr><td>CreateWaitableTimerA</td><td>CreateWaitableTimerW</td><td>CreateWaitableTimerExA</td></tr>
<tr><td>CreateWaitableTimerExW</td><td>OpenWaitableTimerA</td><td>OpenWaitableTimerW</td></tr>
<tr><th colspan="3">File function</th></tr>
<tr><td>CreateFileA</td><td>CreateFileW</td><td>CreateFileTransactedA</td></tr>
<tr><td>CreateFileTransactedW</td><td>FindFirstFileA</td><td>FindFirstFileW</td></tr>
<tr><td>FindFirstFileExA</td><td>FindFirstFileExW</td><td>FindFirstFileNameTransactedW</td></tr>
<tr><td>FindFirstFileNameW</td><td>FindFirstFileTransactedA</td><td>FindFirstFileTransactedW</td></tr>
<tr><td>FindFirstStreamTransactedW</td><td>FindFirstStreamW</td><td>FindClose</td></tr>
<tr><td>OpenFileById</td><td>ReOpenFile</td><td>CreateIoCompletionPort</td></tr>
<tr><th colspan="3">Authorization function</th></tr>
<tr><td>CreateRestrictedToken</td><td>DuplicateToken</td><td>DuplicateTokenEx</td></tr>
<tr><td>OpenProcessToken</td><td>OpenThreadToken</td><td></td></tr>
<tr><th colspan="3">Directory management</th></tr>
<tr><td>FindFirstChangeNotificationA</td><td>FindFirstChangeNotificationW</td><td>FindCloseChangeNotification</td></tr>
<tr><th colspan="3">File mapping</th></tr>
<tr><td>CreateMemoryResourceNotification</td><td>CreateFileMappingA</td><td>CreateFileMappingW</td></tr>
<tr><td>CreateFileMappingNumaA</td><td>CreateFileMappingNumaW</td><td>OpenFileMappingA</td></tr>
<tr><td>OpenFileMappingW</td><td></td><td></td></tr>
<tr><th colspan="3">Memory</th></tr>
<tr><td>HeapCreate</td><td>HeapDestroy</td><td>GlobalAlloc</td></tr>
<tr><td>GlobalReAlloc</td><td>GlobalFree</td><td>LocalAlloc</td></tr>
<tr><td>LocalReAlloc</td><td>LocalFree</td><td></td></tr>
<tr><th colspan="3">Process and thread</th></tr>
<tr><td>CreateProcessA</td><td>CreateProcessW</td><td>CreateProcessAsUserA</td></tr>
<tr><td>CreateProcessAsUserW</td><td>CreateProcessWithLogonW</td><td>CreateProcessWithTokenW</td></tr>
<tr><td>OpenProcess</td><td>CreateThread</td><td>CreateRemoteThread</td></tr>
<tr><td>OpenThread</td><td>CreateJobObjectA</td><td>CreateJobObjectW</td></tr>
<tr><th colspan="3">Mail slot</th></tr>
<tr><td>CreateMailslotA</td><td>CreateMailslotW</td><td></td></tr>
<tr><th colspan="3">pipe</th></tr>
<tr><td>CreatePipe</td><td>CreateNamedPipeA</td><td>CreateNamedPipeW</td></tr>
<tr><th colspan="3">Registry</th></tr>
<tr><td>RegCreateKeyExA</td><td>RegCreateKeyExW</td><td>RegCreateKeyTransactedA</td></tr>
<tr><td>RegCreateKeyTransactedW</td><td>RegOpenCurrentUser</td><td>RegOpenKeyA</td></tr>
<tr><td>RegOpenKeyW</td><td>RegOpenKeyExA</td><td>RegOpenKeyExW</td></tr>
<tr><td>RegOpenKeyTransactedA</td><td>RegOpenKeyTransactedW</td><td>RegOpenUserClassesRoot</td></tr>
<tr><td>RegCreateKeyA</td><td>RegCreateKeyW</td><td>RegCloseKey</td></tr>
<tr><th colspan="3">Common functions</th></tr>
<tr><td>DuplicateHandle</td><td>CloseHandle</td><td></td></tr>
</tbody></table><br />
<div style="text-align: justify;">Note:- I have tried my best to include all the functions I know which allocates or de-allocate resources. Still, if know some function that i have missed, please let me know.</div><div style="text-align: justify;"><br />
Now lets see how the hooking works. For each of the function in the above table LeakMon have a dummy function ( Which is actually 199 dummy functions ). So after hooking, the application will be calling my dummy function instead of the original function. In the dummy function what it does is,</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">1) Call the original function</div><div style="text-align: justify;">2) Create the call stack and store it</div><div style="text-align: justify;">3) Return the return value of retured by original function</div><br />
<div style="text-align: justify;">Let's check the example of HeapAlloc function ( Remember that all the memory allocation functions such as new, malloc etc will finally ends up in calling HeapAlloc function to allocate memory. Similarly free, delete functions calls HeapFree ).</div><div style="height: 152px; margin: 20px auto; overflow: auto; text-align: left; width: 543px;"><div style="text-align: justify;"><span style="color: #e69138;">LPVOID WINAPI MyHeapAlloc( HANDLE hHeap,<br />
DWORD dwFlags,<br />
SIZE_T dwBytes )<br />
{<br />
LPVOID lMem = pOrgHeapAlloc( hHeap, dwFlags, dwBytes );<br />
CreateCallStack( lMem, dwBytes );<br />
return lMem;<br />
}</span></div></div><div style="text-align: justify;">The CreateCallStack function creates the current function call stack and save it in a map. The key of the map is the memory address returned by original HeapAlloc and value is a structure which holds the call stack and size of memory allocated.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Now when the application calls HeapFree, the dummy function just removes the entry from the map and then call the original HeapFree function.</div><div align="left" style="height: 125px; margin: 20px auto; overflow: auto; width: 547px;"><span style="color: #e69138;">BOOL WINAPI MyHeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem )</span><br />
<span style="color: #e69138;">{</span><br />
<span style="color: #e69138;"> RemovCallStack( lpMem );</span><br />
<span style="color: #e69138;"> return pOrgHeapFree( hHeap, dwFlags, lpMem );</span><br />
<span style="color: #e69138;">}</span></div><strong>Creating the Call Stack</strong><br />
<br />
This is the only part which actually has different processing for 64 bit and 32 bit. In 32 bit applications the call stack is created using the StackWalk64 function. You can either check the code ( StackDump function ) or read this nice article <a href="http://www.codeproject.com/KB/threads/StackWalker.aspx">Walking the callstack</a>, to learn more about the StackWalk64 function.<br />
<br />
The stack walking in x64 machine was bit difficult for me. I actually had no idea how to do it. Thanks to <a href="http://www.nynaeve.net/?page_id=2">Ken Johnson</a> for posting an <a href="http://www.nynaeve.net/Code/StackWalk64.cpp">example of stack walking in x64 machine</a> which practically made me to port this application to 64 bit also.<br />
<br />
<strong>Dumping the leaks</strong><br />
<br />
<div style="text-align: justify;">After the hook dll have setup all the hooks, it will wait for couple of events. One among those event is Dump event. When user clicks on the Dump button in the Injector application, it will set the dump event to signalled state. When this event is signalled the thread in the HookDll will start dumping each entry in the map to a user specified file. The format of the dumpfile is mentioned in the <a href="http://0memory.blogspot.com/2011/01/leakmon-track-handle-leak-gdi-leak-and.html">previous post</a>.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">That's all the main thing about the Injector and HookDll. There is one more application DumpViewer, which actually has some nice features done using Visual Studio automation. I will explain those things in another post. </div><br />
<strong>Open Source</strong><br />
<br />
<div style="text-align: justify;">I got couple of request to make this project open source, so I have opened a project in code.google.com and is available at <a href="http://code.google.com/p/leakmon/">http://code.google.com/p/leakmon/</a> . So if you have some idea or got some improvement points you are welcome to join me there. Suggestions are also welcome.</div></div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-4859830208068773392011-01-25T01:38:00.000-08:002013-02-21T06:32:22.466-08:00LeakMon - Track Handle leak, GDI leak and Memory leak in your applications<div dir="ltr" style="text-align: left;" trbidi="on">
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. <br />
<br />
<strong><span style="font-size: large;"><em>Downloads</em></span></strong><br />
<!--[Download from Skydrive]<br />-->
<a href="http://sdrv.ms/Q5DKOf">LeakMon</a><br />
<br />
[Download from Codeproject]<br />
<a href="http://www.codeproject.com/Articles/150463/LeakMon-Track-Handle-leak-GDI-Leak-and-Memory-Leak" target="_blank">LeakMon</a><br />
<br />
<span style="font-size: large;"><em>Prerequisite</em></span><br />
<br />
• You need to have installed VS2010 or Microsoft Visual C++ 2010 Redistributable Package.<br />
<br />
Visual C++ 2010 Redistributable Package can be downloaded from the below path<br />
<br />
For 32 bit applications (4.8 MB) <br />
<br />
<a href="http://www.microsoft.com/downloads/en/details.aspx?familyid=A7B7A05E-6DE6-4D3A-A423-37BF0912DB84&displaylang=en">http://www.microsoft.com/downloads/en/details.aspx?familyid=A7B7A05E-6DE6-4D3A-A423-37BF0912DB84&displaylang=en</a><br />
<br />
For 64 bit application (5.5 MB)<br />
<a href="http://www.microsoft.com/downloads/en/details.aspx?familyid=BD512D9E-43C8-4655-81BF-9350143D5867&displaylang=en">http://www.microsoft.com/downloads/en/details.aspx?familyid=BD512D9E-43C8-4655-81BF-9350143D5867&displaylang=en</a><br />
<br />
<span style="font-size: large;"><em>How to use</em></span><br />
<br />
This tool consists of three binaries, Injector, HookDll and a DumpViewer.<br />
To start with, run the Injector.exe.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp6CPgv6ECvGbn6Bx0E5RQqbw0wH8z2gLpoofBPO2FKx6v9b7bxIzRsIzx3mRsESxm-ybTFjaYTbCBUtQ5nb4533ICXfUDVOMmVBuivoi_mAhijAT7FSdllOCKq0wzTdqBs8_M8fmmh_Q/s1600/Injector.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp6CPgv6ECvGbn6Bx0E5RQqbw0wH8z2gLpoofBPO2FKx6v9b7bxIzRsIzx3mRsESxm-ybTFjaYTbCBUtQ5nb4533ICXfUDVOMmVBuivoi_mAhijAT7FSdllOCKq0wzTdqBs8_M8fmmh_Q/s400/Injector.JPG" width="400" /></a></div>
<br />
• Refresh :- Refresh the process list<br />
• Inject :- Injects the hook DLL to the target process to start tracking of the leak<br />
• Dump : - Dumps the leak found so far to a file.<br />
• Reset: :- Ignore/Clear all the leaks found up to this point.<br />
• 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.<br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt; text-align: justify;">
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).</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXVrLTNWiVY_GxxFH0H35tkxHZeBVzHoRNa_lc_FeDH2KX_Mpc9FCWR92VBFVQchVwPqO0N0RWsAQWRtnu0thi04D8t-YuMN0Nch1khUz5GRj1c0mZqZRLmtnJ8XWBUDU1ZHQ2EL5Fb-w/s1600/SettingsDlg.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="221" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXVrLTNWiVY_GxxFH0H35tkxHZeBVzHoRNa_lc_FeDH2KX_Mpc9FCWR92VBFVQchVwPqO0N0RWsAQWRtnu0thi04D8t-YuMN0Nch1khUz5GRj1c0mZqZRLmtnJ8XWBUDU1ZHQ2EL5Fb-w/s400/SettingsDlg.JPG" width="400" /></a></div>
<br />
<br />
The setting window allows you to choose the “<strong>type of leak</strong>” you want to track. The types include memory leak, GDI leak and Handle leak.<br />
<br />
The next option in the Settings dialog is “<strong>Stack Depth</strong>”. 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 <strong>speed</strong> of the application. Lesser the value, the faster the application will be.<br />
<br />
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, <strong>you will not be able to see the call stack</strong> 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<br />
<br />
<span style="font-family: Calibri; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-: EN-US;">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.</span><br />
<span style="font-family: Calibri; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-: EN-US;"></span><br />
<span style="font-family: Calibri; font-size: xx-small; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-: EN-US;"><em>Analyzing the leak dump file </em></span><br />
<br />
<br />
I will explain the format of the dump file with the following example. Consider the below code<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3fmMuIEug8KPRRQ7X6FGD3KMtKM0ZvWAwj49s88lcErLEkT6e_IvswOa3AlBZzkhXySsJqDJEz7VbhhKU34aJUWeH4jUjBeqI72ImCcWjWWyMILSFCjxu-qM-qiPjLCp5WjX8ZJxT35A/s1600/Function_calls.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3fmMuIEug8KPRRQ7X6FGD3KMtKM0ZvWAwj49s88lcErLEkT6e_IvswOa3AlBZzkhXySsJqDJEz7VbhhKU34aJUWeH4jUjBeqI72ImCcWjWWyMILSFCjxu-qM-qiPjLCp5WjX8ZJxT35A/s1600/Function_calls.JPG" /></a></div>
i.e. The sequence of calling is in the order<br />
<br />
<br />
CMulitThreadDlg::OnBnClickedButton1()->func1()->func2().<br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
Now the information regarding the memory leak in the above code will look as follows.</div>
<br />
<br />
<div>
<div align="left" style="border: 2px solid currentColor; height: 263px; margin: 20px auto; overflow: auto; width: 597px;">
-->Bytes allocated -- 76<br />
<br />
_heap_alloc_base f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c(105)<br />
_heap_alloc_dbg_impl f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(427)<br />
_nh_malloc_dbg_impl f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(239)<br />
_nh_malloc_dbg f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(296)<br />
_malloc_dbg f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c(160)<br />
operator new f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(407)<br />
operator new[] f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(442)<br />
operator new[] f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\afxmem.cpp(67)<br />
<span style="color: red;">func2 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(178)</span><br />
<span style="color: red;">func1 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(184)</span><br />
<span style="color: red;">CMulitThreadDlg::OnBnClickedButton1 t:\naveen\pgms\cpp\2008\mulitthread\mulitthreaddlg.cpp(189)</span><br />
_AfxDispatchCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp(82)<br />
CCmdTarget::OnCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp(381)<br />
CDialog::OnCmdMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp(85)<br />
CWnd::OnCommand f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(2364)<br />
CWnd::OnWndMsg f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(1769)<br />
CWnd::WindowProc f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp(1755)</div>
</div>
<span style="font-family: Calibri; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US;">Starting from the top function, traverse down, until you find a function from your file. In the above case, func2().<span style="mso-spacerun: yes;"> </span>So it can be concluded that, some memory that has allocated from the func2() haven’t de-allocated.</span> <br />
<br />
<span style="font-size: large;"><em>Analyzing the leak with DumpViewer</em></span><br />
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEg62lxwkxoshnLtVGNkRmroPgPIXX0f9NdtbL6vJ5psvoJdx_zqlTIet1jwJE2MabHmABtJckyggk5UmuAs3WJGK37bbXM7-NWAJtGZwgfohgCi5wDP4SmdyNMwZtwOz0kfgS7vE9iH4/s1600/DumpViewer.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEg62lxwkxoshnLtVGNkRmroPgPIXX0f9NdtbL6vJ5psvoJdx_zqlTIet1jwJE2MabHmABtJckyggk5UmuAs3WJGK37bbXM7-NWAJtGZwgfohgCi5wDP4SmdyNMwZtwOz0kfgS7vE9iH4/s640/DumpViewer.JPG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<em><span style="font-size: large;">Under the Hood</span></em></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
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.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
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.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
[Update] :- Part 2 <a href="http://0memory.blogspot.com/2011/03/leakmon-part-2-under-hood.html">Leakmon- Under the hood</a></div>
</div>
Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com16tag:blogger.com,1999:blog-8614819832544366718.post-49896989856436680152009-10-20T12:28:00.000-07:002009-10-20T13:52:47.816-07:00Dependency Checker<div align="justify">This is a simple light weight utility to find which all dll/exe/ocx in a folder uses a particular dll.</div><strong>Download<br /></strong><a href="http://www.easy-share.com/1908192288/DependsChecker_bin.zip"><span style="font-size:85%;">Source File(DependsChecker_Src.zip)</span><br /><span style="font-size:85%;">Execuatble(DependsChecker_bin.zip)</span><br /></a><br /><p align="center"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVXaMNklqcsJaCXWhv0Nx9_dM9-yM_rNZz_JmukPWgjyPMG2vo_0cQmKVLJMD-PMV28C8IYz3AL7zdXQyi3yHIZ_PeAD30pZ0_w9433VLfytWVRLBz329ZXvEvJQJ19h8qTPxaqrWcAzg/s800/Untitled.jpg" /></p><div align="justify">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.</div><p><span style="font-size:130%;">How to Use</span></p><ol><li>In the “Dll Name” edit box, enter the name of the dll for which we have to search for.</li><li>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.</li><li>Click “Start” button.</li></ol><p></p>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”.<br /><p><span style="font-size:130%;">How it works</span><br /><div align="justify"><p></p><p>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.<br />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.<br /></p><div style="BORDER-BOTTOM: 2px solid; BORDER-LEFT: 2px solid; MARGIN: 20px auto; WIDTH: 535px; HEIGHT: 263px; OVERFLOW: auto; BORDER-TOP: 2px solid; BORDER-RIGHT: 2px solid" align="left"><br /><p><span style="color:#ff6600;">CFile fl;<br />if( !fl.Open( csExeName, CFile::modeReadCFile::shareDenyNone, 0 ))<br />{<br />CString csMsg;<br />csMsg.Format( _T(" Failed to open file %s"), csExeName );<br />AfxMessageBox( csMsg );<br />continue;<br />}<br />HANDLE hSM = CreateFileMapping( (HANDLE)fl.m_hFile, 0,PAGE_READONLY,0,0, _T("some_sM"));<br />LPVOID pBinary = MapViewOfFile( hSM,FILE_MAP_READ,0,0, fl.GetLength());<br />if( CheckForDependecy( csDllName, pBinary ))<br />{<br />m_List.InsertItem( 0, fl.GetFileName() );<br />}<br />UnmapViewOfFile( pBinary );<br />CloseHandle( hSM );<br />fl.Close();</span></p></div><p></p></div><div align="justify">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.</div><span style="color:#ff6600;">PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) lpStartAddress;</span><br /><div align="justify">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.</div><br /><div style="BORDER-BOTTOM: 2px solid; BORDER-LEFT: 2px solid; MARGIN: 20px auto; WIDTH: 545px; HEIGHT: 172px; OVERFLOW: auto; BORDER-TOP: 2px solid; BORDER-RIGHT: 2px solid"><br /><p><span style="color:#ff6600;">// Get the PE header.<br />PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);<br />if( IsBadReadPtr( pNTHeader, sizeof( IMAGE_NT_HEADERS)))<br />{<br />return false;<br />};</span></p></div><div align="justify">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).</div><br /><div style="BORDER-BOTTOM: 2px solid; BORDER-LEFT: 2px solid; MARGIN: 20px auto; WIDTH: 527px; HEIGHT: 151px; OVERFLOW: auto; BORDER-TOP: 2px solid; BORDER-RIGHT: 2px solid"><br /><p><span style="color:#ff6600;">char* pSig = (char*)&pNTHeader->Signature;<br />if( pSig[0] != 'P' pSig[1] != 'E')<br />{<br />return false;<br />}</span></p></div><div align="justify">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 )</div><br /><div style="BORDER-BOTTOM: 2px solid; BORDER-LEFT: 2px solid; MARGIN: 20px auto; WIDTH: 521px; HEIGHT: 348px; OVERFLOW: auto; BORDER-TOP: 2px solid; BORDER-RIGHT: 2px solid"><br /><p><span style="color:#ff6600;"><br />PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageRvaToVa( pNTHeader, lpStartAddress, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].<br />VirtualAddress, 0 );<br />while( pImportDesc && pImportDesc->Name )<br />{<br />// pImportDesc->Name holds the name of the import library<br />PVOID pName = ImageRvaToVa( pNTHeader, lpStartAddress, pImportDesc->Name , 0 );<br />PSTR szCurrMod = (PSTR)pName;<br />if( IsBadReadPtr( szCurrMod, 1 ))<br />{<br />continue;<br />}<br />CString cs = szCurrMod;<br />if( 0 == cs.CollateNoCase( csDllName ))<br />{<br />// everything pass. We have found one dependency<br />return true;<br />}<br />// Move to the next import library<br />pImportDesc++;<br />}</span></p></div><div>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 ).<br /></div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com4tag:blogger.com,1999:blog-8614819832544366718.post-81860871871006487752009-04-18T09:05:00.000-07:002009-04-18T10:02:07.479-07:00Centralizing modeless child dialog<div align="justify">Normally when we call the DoModal() function of a dialog, the dialog will created and displayed at the center of the parent dialog.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvgylzD0GYRRgQbGydLMMYLKXBcOt6copfMZHOz0F8NZoCotbzBuIxMcV2BLWc1AKHNhlsFvk2VM6-YdobMxUorzpf1jEs3npJTOjnQwWY8_C5BNVdRfbKhh6zViTdyNhP2qnnwH6oDdY/"><img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; CURSOR: hand" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvgylzD0GYRRgQbGydLMMYLKXBcOt6copfMZHOz0F8NZoCotbzBuIxMcV2BLWc1AKHNhlsFvk2VM6-YdobMxUorzpf1jEs3npJTOjnQwWY8_C5BNVdRfbKhh6zViTdyNhP2qnnwH6oDdY/" /></a><br /><br />But when a modless dialog is displayed, the child dialog will be displayed at the top left portion of the parent dialog.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvgylzD0GYRRgQbGydLMMYLKXBcOt6copfMZHOz0F8NZoCotbzBuIxMcV2BLWc1AKHNhlsFvk2VM6-YdobMxUorzpf1jEs3npJTOjnQwWY8_C5BNVdRfbKhh6zViTdyNhP2qnnwH6oDdY/"><img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; CURSOR: hand" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHtyRP8az_gMTAwTOUmRbjz-KDracHOemUVxbQgfNfdCF4up0zXxxyskgBQ7Pg2sVir15HB3cFPqzKqIWk2t_l2bctCB243GI5SFyY7Arjl0u2kqiZH5jT6RfcxqjztOW27bUhPOAb75Q/" /></a><br /><br />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 <span style="color:#ff6600;">DoModal()</span> function. So I stepped into the <span style="color:#ff6600;">DoModal()</span> function. But I couldn't find any difference in the dialog creation in CDialog::DoModal and <span style="color:#ff6600;">CDialog::Create()</span>.<br />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 <span style="color:#ff6600;">DoModal()</span> function. To try my luck I disabled the parent window before calling the <span style="color:#ff6600;">Create</span> function of dialog. Surprisingly it worked! The modeless child dialog came at the center of parent dialog.<br /><br />So if you want to centralize a modeless dialog, just disable the parent dialog before create and re-enable it after the creation.<br /></div><pre><span style="color:#ff6600;">void CDialogBased2Dlg::OnBnClickedButton1()<br />{<br /> EnableWindow( FALSE );<br /> m_ChildDlg.Create( ChildDialog::IDD, this );<br /> EnableWindow( TRUE );<br /> m_ChildDlg.ShowWindow( SW_SHOW );<br />}</span></pre>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com2tag:blogger.com,1999:blog-8614819832544366718.post-74558247449620533962008-12-20T08:21:00.000-08:002009-04-07T09:28:15.075-07:00Function to get the local system Administrator Name<div align="justify">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.</div><pre><span style="font-size:85%;color:#ff6600;">LPLOCALGROUP_MEMBERS_INFO_1 pstMembersInfo = 0;<br />DWORD entriesread = 0;<br />DWORD totalentries = 0;<br />if( 0 != NetLocalGroupGetMembers( NULL, _T("Administrators"), 1, (LPBYTE*)<br /> &pstMembersInfo,MAX_PREFERRED_LENGTH,<br /> &entriesread, &totalentries, 0 ))<br />{<br /> AfxMessageBox( _T("NetLocalGroupGetMembers failed !"));<br /> return ;<br />}<br />for( DWORD dwIdx =0; dwIdx < entriesread; dwIdx ++ )<br />{<br /> AfxMessageBox( pstMembersInfo[dwIdx].lgrmi1_name );<br />}<br />NetApiBufferFree( pstMembersInfo );<br /></span></pre>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-42057931419234405222008-10-27T17:47:00.000-07:002009-04-07T09:28:15.075-07:00How to find whether the parent process is GUI or ConsoleThis 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.<br /><br /><span style="color:#cc6600;"><pre>if( AttachConsole( ATTACH_PARENT_PROCESS ))<br />{<br /> AfxMessageBox( _T("Parent process is a console application"));<br />}<br />else<br />{<br /> AfxMessageBox( _T("Parent process is not a console application"));<br />}<br /></pre></span>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com2tag:blogger.com,1999:blog-8614819832544366718.post-86060026022307114912008-08-26T22:53:00.000-07:002009-04-07T09:28:15.075-07:00new with empty bracket<div align="justify">Have you ever wrote a statement like..<br /><br /><span style="color:#ff6600;">int *pnValue = new int[];<br /></span><br />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.<br /><br />OK now the question is, what will be size of memory that pnValue points?<br /><br />The two API's in windows that allocates and de allocates the memeory are <span style="color:#ff6600;">HeapAlloc</span> and <span style="color:#ff6600;">HeepFree</span>. The CRT functions <span style="color:#ff6600;">malloc</span> and <span style="color:#ff6600;">free</span> are actually wrappers the above API. The <span style="color:#ff6600;">new, new[], delete, delete[] </span>are again another wrapper around the <span style="color:#ff6600;">malloc</span> and <span style="color:#ff6600;">free</span>. So when ever you allocates some memory using <span style="color:#ff6600;">new</span> or <span style="color:#ff6600;">new[]</span>, it will finally reach the HeapAlloc function. This function is defined as<br /><br /><span style="color:#ff6600;">LPVOID WINAPI HeapAlloc(<br />__in HANDLE hHeap,<br />__in DWORD dwFlags,<br />__in SIZE_T dwBytes<br />);</span><br /><br />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 "<span style="color:#ff6600;">new int[]"</span> returns, we can put a break point in the entry point of <span style="color:#ff6600;">HeapAlloc</span> and check the value of dwBytes( in dis assembly ).<br /><br />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.<br /><br />Another interesting thing is <span style="color:#ff6600;">"int *pnValue = new int[0];"</span> also returns a pointer pointing a memory of 1 byte long.</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com1tag:blogger.com,1999:blog-8614819832544366718.post-5877724327668478222008-08-20T08:41:00.000-07:002009-04-07T09:28:15.075-07:00How to open Popup Blocker Settings window of IE programmaticallyHow to open Popup Blocker Settings window of IE programmatically??<br /><br />Well it is with the help of "<span style="color:#cc6600;">DisplayPopupWindowManagementDialog</span>" function in the "<span style="color:#cc6600;">C:\WINDOWS\system32\inetcpl.cpl</span>".<br /><br /><div align="justify">But here rather just showing a misterious function, I would like to explain the methods by which I found out the name of function.<br /><br />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.<br /><br /></div><div align="justify">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 <a href="http://www.dennisbabkin.com/php/download.php?what=WinID">WinID</a>[<a title="New Window" href="http://www.dennisbabkin.com/php/download.php?what=WinID" target="_blank">^</a>] with which we can find which dll created a perticular windows. In one of my previous post, I have explained <a href="http://0memory.blogspot.com/2008/03/find-which-dll-exe-created-window.html">How to find which dll / exe created a window.</a>[<a title="New Window" href="http://0memory.blogspot.com/2008/03/find-which-dll-exe-created-window.html" target="_blank">^</a>] using code. Below is a screenshot of what WinID showed me for the "Popup Blocker Settings" dialog .<br /><br /></div><p><a href="http://lh6.ggpht.com/nave432/SK7ZiyzM90I/AAAAAAAAA70/K3yI68Hl4W4/s144/winid.jpg"><img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://lh6.ggpht.com/nave432/SK7ZiyzM90I/AAAAAAAAA70/K3yI68Hl4W4/s400/winid.jpg" border="0" /></a><br /><br />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...<br /><br />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 <span style="color:#ff6600;">GetWindowThreadProcessId</span> 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 ).<br /><br />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.<br /><br /><a href="http://lh6.ggpht.com/nave432/SK7kLt6tY9I/AAAAAAAAA8U/6t3rQJqhIto/s144/processexp.jpg"><img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 550px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://lh6.ggpht.com/nave432/SK7kLt6tY9I/AAAAAAAAA8U/6t3rQJqhIto/s800/processexp.jpg" border="0" /></a><br /><br />And in the call stack, there was only one un familiar dll and function the "inetcpl.cpl" and the <span style="color:#ff6600;">DisplayPopupWindowManagementDialog</span> 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.<br /><br />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 <a href="http://www.microsoft.com/msj/1199/c/c1199.aspx">Paul DiLascia's Q&A</a>[<a title="New Window" href="http://www.microsoft.com/msj/1199/c/c1199.aspx" target="_blank">^</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!!!!<br /><br />And ho ya here is the sample code..<br /><br /></p><pre><span style="color:#ff6600;">typedef BOOL (WINAPI *DisplayPopupWindowP)( HANDLE hWnd, LPCTSTR lpCaption );<br />void CDialogBasedDlg::OnBnClickedButton1()<br />{<br /> HMODULE hModule = LoadLibrary( _T("inetcpl.cpl") );<br /> DisplayPopupWindowP DisplayPopupWindowManagementDialog =<br /> ( DisplayPopupWindowP)GetProcAddress(hModule,<br /> "DisplayPopupWindowManagementDialog" );<br /> if( !DisplayPopupWindowManagementDialog )<br /> {<br /> return;//error<br /> }<br /> DisplayPopupWindowManagementDialog( m_hWnd, <br /> _T("www.Sitetounblock.com"));<br />}</span></pre>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-76818066657616119162008-08-17T00:30:00.000-07:002009-04-07T09:28:15.075-07:00GetFinalPathNameByHandle API Hungs<div align="justify"><a href="http://msdn.microsoft.com/en-us/library/aa364962(VS.85).aspx">GetFinalPathNameByHandle</a> is an new API introduced in windows vista. As you can read from MSDN, the purpose of this API is to return the file name corresponding to a file handle .<br /><br />Some months back, I have written a small utility <a href="http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx">OpenedFileFinder</a> which list all the file that are opened under a certain folder. While writing this application,the main problem I came across was to get the file name from the handle. Initially I used a function called <span style="color:#cc6600;">NtQueryObject().</span> But the problem with this API is that if we try to query the details for certain object such as pipes, directory handles etc, it will hangs. So in my application finally I have to introduce a driver to get round of this hanging problem. When I found the new <span style="color:#ff6600;">GetFinalPathNameByHandle()</span>, I was so happy and I thought at least I can avoid the driver in the vista. So I had a try on this API. But I came to find that this API also have the same hanging problem which I described earlier.<br /><br />It seems the <span style="color:#ff6600;">GetFinalPathNameByHandle</span> is also using the same <span style="color:#cc6600;">NtQueryObject()</span> to get the file name and so it hangs. Any how, I have reported this bug to the <a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362169">microsoft connect</a>. Let us see how they solve the problem.<br /><br />Another API, that worth mentioning here is <a href="http://msdn.microsoft.com/en-us/library/aa364953(VS.85).aspx">GetFileInformationByHandleEx()</a>, which is also a new API introduced in Vista. Using this API also, I can get the file name from a handle. So I decided to check whether the same problem exists in this API also. Surprisingly it worked fine. And in MSDN also it is mentioned that it uses a driver for attaining the task. So I highly suggest every one to use <span style="color:#cc6600;">GetFileInformationByHandleEx()</span> API instead of <span style="color:#ff6600;">GetFinalPathNameByHandle()</span>.</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com7tag:blogger.com,1999:blog-8614819832544366718.post-78428068626897882482008-06-19T20:43:00.000-07:002009-04-07T09:28:15.076-07:00How Local Static Variable Is Implemented in vc++<div align="justify">As every one knows, static variables are initialized only ones, even though it is declared in a function. In this post, I will explain how the compiler implements this.<br /><br />OK let start with the storage of the static variables. Where do you think a static variable declared inside a function is stored? If your answer is on the stack, you are wrong. All static and global variables are stored in a section called ".data" in the exe. For example check the below code.<br /></div><pre><span style="color:#ff6600;">int g_GlobalVariable = 0x10;<br />static int nValue1 = 0x11;<br />void main()<br />{<br /> static int nValue2 = 0x12;<br /> // Take the address<br /><br /> int *pglobal = &g_GlobalVariable;<br /> int *pValue1 = &nValue1;<br /> int *pValue2 = &nValue2;<br />}</span></pre><div align="justify">When executed, the values of pglobal, pValue1 and pValue2 were 0x408020, 0x408024 and 0x408028 respectively. Which means, all the three variables were stored in three consecutive locations. In the PE view we can see these variables stored in the ".data" section.<br /><br /><br /><br /></div><img id="BLOGGER_PHOTO_ID_5213822265702762882" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigpbBERSa9xRfiQOrDN12IvK8Q4hFxFWmjErYX3WkL2V2OCKvZSYX288BuhEOkp4LDT0bGlhOAmCt01nR6Wep82jX9z6_TCiKDbFh5NK4v65XIia06XuSyqk1JZlSH7pSOdSPtVdI393w/s400/peview.bmp" border="0" /><br /><br /><p align="justify">You can see that the "<em><span style="color:#ff6600;">nValue2</span></em>" variable is initialized at the compile time itself. so no instruction is generated by the compiler for a statement like <span style="color:#ff6600;">static int nValue2 = 0x12;</span></p><p align="justify">So compiler did a nice job by setting the value to variable at the compile time itself. But that was a C type object. What if we declare a static C++ object inside a function. This time the compiler cannot initialize the variable at the compile time because the constructor need to be invoked to initialize a C++ object. Consider the below code</p><pre><span style="font-size:85%;color:#ff6600;">class TestClass<br />{<br />public:<br /> TestClass()<br /> {<br /> m_nMemeberVar = 10;<br /> }<br /> int m_nMemeberVar;<br />};<br />TestClass& AFunction()<br />{<br /> static TestClass cppObject;<br /> return cppObject;<br />}</span></pre><p align="justify">In the above code, the <span style="color:#ff6600;">AFunction() </span>function creates a static object of class <span style="color:#ff6600;">TestClass</span> and as you know the cppObject will be initialized only once. How does the compiler manages to do it? Well answer is compiler keeps a flag!!! I.e when the compiler sees a c++, static object is declared inside a function, it will create a global byte variable with value 0 and some addition instruction such that the constructor of the object will be called only if the value of the byte variable is 0 and it also set the value of the byte variable as 1. So from the next time onwards, the constructor will not be called. Below is the dis assembly for the statement <span style="color:#ff6600;">static TestClass cppObject.</span></p><pre><span style="color:#ff6600;">static TestClass cppObject;</span></pre><pre><span style="color:#ff6600;">// Zero out the eax register<br />00401E79 xor eax,eax</span></pre><pre><span style="color:#ff6600;">// Copy the flag variable to al register<br />00401E7B mov al,[`AFunction'::`2'::$S230 (00408104)]<br />00401E80 and eax,1</span></pre><pre><span style="color:#ff6600;">// Check eax equal to zero<br />00401E83 test eax,eax</span></pre><pre><span style="color:#ff6600;">// If it is not zero, go to end.<br />00401E85 jne AFunction+3Dh (00401ead)</span></pre><pre><span style="color:#ff6600;">// Copy the flag variable to the cl register<br />00401E87 mov cl,byte ptr [`AFunction'::`2'::$S230 (00408104)]</span></pre><pre><span style="color:#ff6600;">// cl = 1<br />00401E8D or cl,1</span></pre><pre><span style="color:#ff6600;">// Copy back the content of cl register to the flag variable<br />00401E90 mov byte ptr [`AFunction'::`2'::$S230 (00408104)],cl</span></pre><pre><span style="color:#ff6600;">// Call the constructor of cppObject<br />00401E96 mov ecx,offset theApp+0C8h (00408100)<br />00401E9B call TestClass::TestClass (00401ec0)</span><br /></pre>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-25623349726015913332008-05-05T02:01:00.000-07:002009-04-07T09:28:15.076-07:00Optimizing Storage for Constant Data<div align="justify">In programs we usually declare constant string data. Like..<br /><br /><span style="color:#ff6600;">const char* g_pchar = "this is a string";</span><br /><br />You might be knowing that if we run multiple copies of a exe or dll, the code portion is not duplicated per process. So do the constant data. This is because the constant datas are stored in a special section of exe called ".rdata"( The code protion is stored in the ".text" section ). But guess what will happen if we have declaration like..<br /><br /><span style="color:#ff6600;">const CString g_str("this is the worst thing I can do");</span><br /><br />Now you've got the CString object (which is quite small) in the .bss section( .bss section stores nonconstant uninitialized data ), and you've also got a character array in the .data section( Nonconstant initialized data ), neither of which can be backed by the EXE file. To make matters worse, when the program starts, the CString class must allocate heap memory for a copy of the characters. You would be much better off using a const character array instead of a CString object. So never ever declare like that ( Reference "Programming Microsoft vc++" by David Kruglinski ).<br /><br />OK that was the theory. Now the reason why I stated the above theory is that, last week, I installed the latest VS 2008 feature pack. This feature pack had some new classes for MFC. So I decided to check out the new classes. The CWinAppEx is on among them. On the very first function I stepped in( constructor of the CWinAppEx ), I found the following piece of code..<br /><br /><span style="color:#ff6600;">const CString strRegEntryNameWorkspace = _T("Workspace");<br />m_strRegSection = strRegEntryNameWorkspace;<br /></span></div><br />ops . And when I scrolled up, there was another bunch of similar codes<br /><br /><div align="justify"></div><div align="justify"><span style="color:#ff6600;">static const CString strRegEntryNameControlBars = _T("\\ControlBars");<br />static const CString strWindowPlacementRegSection = _T("WindowPlacement");<br />static const CString strRectMainKey = _T("MainWindowRect");<br />static const CString strFlagsKey = _T("Flags");<br />static const CString strShowCmdKey = _T("ShowCmd");<br />static const CString strRegEntryNameSizingBars = _T("\\SizingBars");<br />static const CString strRegEntryVersion = _T("ControlBarVersion");<br />static const CString strVersionMajorKey = _T("Major");<br />static const CString strVersionMinorKey = _T("Minor");</span><br /><br />I dont think any one has seen such a badly written, poor quality code in the old MFC 4 code. Never did I. If MFC starts like this, where will the developers using MFC ends?<br /><br />When I discussed about this in code project and MSDN forum, I got some interesting response. That's how I came to here about <a href="http://en.wikipedia.org/wiki/Wirth">Wirth's law</a>[<a title="New Window" href="http://en.wikipedia.org/wiki/Wirth" target="_blank">^</a>] , which states<br /><br /><strong><em>Software gets slower, faster than hardware gets faster.</em></strong><br />or<br /><strong><em>Software is decelerating faster than hardware is accelerating.</em></strong><br /><br />Very true and you just saw one example.</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com2tag:blogger.com,1999:blog-8614819832544366718.post-9494871894578138822008-04-21T17:13:00.000-07:002009-04-07T09:28:15.076-07:00Loader snapsIn one of my previous post, I mentioned about breaking the executing on dll Load. This post is actually a continutation of that one.<br /><br />Normally if we start an application from the debugger in the debugging mode, the output window shows some messages as shown below.<br /><br /><div style="BORDER-RIGHT: 2px solid; BORDER-TOP: 2px solid; MARGIN: 20px auto; OVERFLOW: auto; BORDER-LEFT: 2px solid; WIDTH: 500px; BORDER-BOTTOM: 2px solid"><pre><em><span style="color:#ff6600;">Loaded 'c:\WINDOWS\system32\calc.exe', no matching symbolic information found.</span></span></em><br /><em><span style="color:#ff6600;">Loaded 'ntdll.dll', no matching symbolic information found.</span></em><br /><em><span style="color:#ff6600;">Loaded 'C:\WINDOWS\system32\kernel32.dll', no matching symbolic information found.</span></em><br /><em><span style="color:#ff6600;">Loaded 'C:\WINDOWS\system32\shell32.dll', no matching symbolic information found.</span></em><br /><em><span style="color:#ff6600;">Loaded 'C:\WINDOWS\system32\advapi32.dll', no matching symbolic information found.</span></em><br /><em><span style="color:#ff6600;">Loaded 'C:\WINDOWS\system32\rpcrt4.dll', no matching symbolic information found.</span></em><br /><em><span style="color:#ff6600;">Loaded 'C:\WINDOWS\system32\secur32.dll', no matching symbolic information found.</span></em></pre></div><div align="justify">Actually it is debugger who shows this messages. But if want, you can ask for more information and traces of the loading process, to the loader. I.e, there is flag in the registry, which specifies the Loader to show more information about the loading process. To show those snaps, you have to added a DWORD value with name "GlobalFlag" under the</div><div align="justify">"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", set its value to 2 and then restart machine.<br /><br />Below is the loader snaps of calc.exe after setting the flag.</div><div style="BORDER-RIGHT: 2px solid; BORDER-TOP: 2px solid; MARGIN: 20px auto; OVERFLOW: auto; BORDER-LEFT: 2px solid; WIDTH: 500px; BORDER-BOTTOM: 2px solid; HEIGHT: 263px"><p><span style="color:#ff6600;">Loaded 'c:\WINDOWS\system32\calc.exe', no matching symbolic information found. Loaded 'ntdll.dll', no matching symbolic information found.<br />Loaded 'C:\WINDOWS\system32\kernel32.dll', no matching symbolic information found.<br />LDR: LdrLoadDll, loading ShimEng.dll from<br />LDR: Loading (DYNAMIC, NON_REDIRECTED) c:\WINDOWS\system32\ShimEng.dll<br />Loaded 'C:\WINDOWS\system32\shimeng.dll', no matching symbolic information found.<br />LDR: ShimEng.dll bound to ntdll.dll<br />LDR: ShimEng.dll has correct binding to ntdll.dll<br />LDR: ShimEng.dll bound to KERNEL32.dll<br />LDR: ShimEng.dll has stale binding to KERNEL32.dll<br />LDR: Stale Bind KERNEL32.dll from ShimEng.dll<br />LDR: LdrGetProcedureAddress by NAME - SE_InstallBeforeInit<br />LDR: LdrGetProcedureAddress by NAME - SE_InstallAfterInit<br />LDR: LdrGetProcedureAddress by NAME - SE_DllLoaded<br />LDR: LdrGetProcedureAddress by NAME - SE_DllUnloaded<br />LDR: LdrGetProcedureAddress by NAME - SE_GetProcAddress<br />LDR: LdrGetProcedureAddress by NAME - SE_ProcessDying<br />LDR: LdrGetDllHandle, searching for ShimEng.dll from<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\AppPatch\AcGenral.DLL from<br />LDR: LdrLoadDll, loading C:\WINDOWS\AppPatch\AcGenral.DLL from<br />LDR: Loading (DYNAMIC, NON_REDIRECTED) C:\WINDOWS\AppPatch\AcGenral.DLL<br />Loaded 'C:\WINDOWS\AppPatch\AcGenral.dll', no matching symbolic information found.<br />LDR: AcGenral.DLL bound to ntdll.dll<br />LDR: AcGenral.DLL has correct binding to ntdll.dll<br />LDR: AcGenral.DLL bound to KERNEL32.dll<br />LDR: AcGenral.DLL has stale binding to KERNEL32.dll<br />LDR: AcGenral.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: AcGenral.DLL has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from AcGenral.DLL<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: AcGenral.DLL bound to USER32.dll<br />LDR: AcGenral.DLL has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to GDI32.dll<br />LDR: AcGenral.DLL has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to ADVAPI32.dll<br />LDR: AcGenral.DLL has correct binding to ADVAPI32.dll<br />LDR: AcGenral.DLL bound to WINMM.dll<br />LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\WINMM.dll<br />Loaded 'C:\WINDOWS\system32\winmm.dll', no matching symbolic information found.<br />LDR: WINMM.dll bound to ntdll.dll<br />LDR: WINMM.dll has correct binding to ntdll.dll<br />LDR: WINMM.dll bound to USER32.dll<br />LDR: WINMM.dll has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from WINMM.dll<br />LDR: WINMM.dll bound to GDI32.dll<br />LDR: WINMM.dll has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from WINMM.dll<br />LDR: WINMM.dll bound to KERNEL32.dll<br />LDR: WINMM.dll has stale binding to KERNEL32.dll<br />LDR: WINMM.dll bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: WINMM.dll has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from WINMM.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: WINMM.dll bound to ADVAPI32.dll<br />LDR: WINMM.dll has correct binding to ADVAPI32.dll<br />LDR: WINMM.dll bound to RPCRT4.dll<br />LDR: WINMM.dll has stale binding to RPCRT4.dll<br />LDR: Stale Bind RPCRT4.dll from WINMM.dll<br />LDR: AcGenral.DLL has correct binding to WINMM.dll<br />LDR: AcGenral.DLL bound to ole32.dll<br />Loaded 'C:\WINDOWS\system32\ole32.dll', no matching symbolic information found.<br />LDR: ADVAPI32.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from ADVAPI32.dll<br />LDR: GDI32.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from GDI32.dll<br />LDR: KERNEL32.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from KERNEL32.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: msvcrt.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from msvcrt.dll<br />LDR: ntdll.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from ntdll.dll<br />LDR: RPCRT4.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from RPCRT4.dll<br />LDR: USER32.dll used by ole32.dll<br />LDR: Snapping imports for ole32.dll from USER32.dll<br />LDR: AcGenral.DLL has stale binding to ole32.dll<br />LDR: Stale Bind ole32.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to OLEAUT32.dll<br />Loaded 'C:\WINDOWS\system32\oleaut32.dll', no matching symbolic information found.<br />LDR: ADVAPI32.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from ADVAPI32.dll<br />LDR: GDI32.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from GDI32.dll<br />LDR: KERNEL32.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from KERNEL32.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: msvcrt.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from msvcrt.dll<br />LDR: ole32.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from ole32.dll<br />LDR: RPCRT4.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from RPCRT4.dll<br />LDR: USER32.dll used by OLEAUT32.dll<br />LDR: Snapping imports for OLEAUT32.dll from USER32.dll<br />LDR: AcGenral.DLL has stale binding to OLEAUT32.dll<br />LDR: Stale Bind OLEAUT32.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to MSACM32.dll<br />LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\MSACM32.dll<br />Loaded 'C:\WINDOWS\system32\msacm32.dll', no matching symbolic information found.<br />LDR: MSACM32.dll bound to msvcrt.dll<br />LDR: MSACM32.dll has stale binding to msvcrt.dll<br />LDR: Stale Bind msvcrt.dll from MSACM32.dll<br />LDR: MSACM32.dll bound to ntdll.dll<br />LDR: MSACM32.dll has correct binding to ntdll.dll<br />LDR: MSACM32.dll bound to USER32.dll<br />LDR: MSACM32.dll has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from MSACM32.dll<br />LDR: MSACM32.dll bound to GDI32.dll<br />LDR: MSACM32.dll has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from MSACM32.dll<br />LDR: MSACM32.dll bound to KERNEL32.dll<br />LDR: MSACM32.dll has stale binding to KERNEL32.dll<br />LDR: MSACM32.dll bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: MSACM32.dll has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from MSACM32.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: MSACM32.dll bound to ADVAPI32.dll<br />LDR: MSACM32.dll has correct binding to ADVAPI32.dll<br />LDR: MSACM32.dll bound to WINMM.dll<br />LDR: MSACM32.dll has correct binding to WINMM.dll<br />LDR: AcGenral.DLL has correct binding to MSACM32.dll<br />LDR: AcGenral.DLL bound to VERSION.dll<br />Loaded 'C:\WINDOWS\system32\version.dll', no matching symbolic information found.<br />LDR: VERSION.dll bound to KERNEL32.dll<br />LDR: VERSION.dll has stale binding to KERNEL32.dll<br />LDR: VERSION.dll bound to NTDLL.DLL via forwarder(s) from kernel32.dll<br />LDR: VERSION.dll has correct binding to NTDLL.DLL<br />LDR: Stale Bind KERNEL32.dll from VERSION.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: VERSION.dll bound to NTDLL.DLL<br />LDR: VERSION.dll has correct binding to NTDLL.DLL<br />LDR: AcGenral.DLL has correct binding to VERSION.dll<br />LDR: AcGenral.DLL bound to SHELL32.dll<br />LDR: AcGenral.DLL has stale binding to SHELL32.dll<br />LDR: Stale Bind SHELL32.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to SHLWAPI.dll<br />LDR: AcGenral.DLL has stale binding to SHLWAPI.dll<br />LDR: Stale Bind SHLWAPI.dll from AcGenral.DLL<br />LDR: AcGenral.DLL bound to USERENV.dll<br />Loaded 'C:\WINDOWS\system32\userenv.dll', no matching symbolic information found.<br />LDR: USERENV.dll bound to msvcrt.dll<br />LDR: USERENV.dll has stale binding to msvcrt.dll<br />LDR: Stale Bind msvcrt.dll from USERENV.dll<br />LDR: USERENV.dll bound to ntdll.dll<br />LDR: USERENV.dll has correct binding to ntdll.dll<br />LDR: USERENV.dll bound to ADVAPI32.dll<br />LDR: USERENV.dll has correct binding to ADVAPI32.dll<br />LDR: USERENV.dll bound to KERNEL32.dll<br />LDR: USERENV.dll has stale binding to KERNEL32.dll<br />LDR: USERENV.dll bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: USERENV.dll has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from USERENV.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: USERENV.dll bound to RPCRT4.dll<br />LDR: USERENV.dll has stale binding to RPCRT4.dll<br />LDR: Stale Bind RPCRT4.dll from USERENV.dll<br />LDR: USERENV.dll bound to USER32.dll<br />LDR: USERENV.dll has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from USERENV.dll<br />LDR: AcGenral.DLL has correct binding to USERENV.dll<br />LDR: AcGenral.DLL bound to UxTheme.dll<br />LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\UxTheme.dll<br />Loaded 'C:\WINDOWS\system32\uxtheme.dll', no matching symbolic information found.<br />LDR: UxTheme.dll bound to msvcrt.dll<br />LDR: UxTheme.dll has stale binding to msvcrt.dll<br />LDR: Stale Bind msvcrt.dll from UxTheme.dll<br />LDR: UxTheme.dll bound to ntdll.dll<br />LDR: UxTheme.dll has correct binding to ntdll.dll<br />LDR: UxTheme.dll bound to KERNEL32.dll<br />LDR: UxTheme.dll has stale binding to KERNEL32.dll<br />LDR: UxTheme.dll bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: UxTheme.dll has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from UxTheme.dll<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: UxTheme.dll bound to USER32.dll<br />LDR: UxTheme.dll has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from UxTheme.dll<br />LDR: UxTheme.dll bound to GDI32.dll<br />LDR: UxTheme.dll has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from UxTheme.dll<br />LDR: UxTheme.dll bound to ADVAPI32.dll<br />LDR: UxTheme.dll has correct binding to ADVAPI32.dll<br />LDR: AcGenral.DLL has correct binding to UxTheme.dll<br />LDR: Refcount WINMM.dll (1)<br />LDR: Refcount ole32.dll (1)<br />LDR: Refcount OLEAUT32.dll (1)<br />LDR: Refcount ole32.dll (2)<br />LDR: Refcount MSACM32.dll (1)<br />LDR: Refcount WINMM.dll (2)<br />LDR: Refcount VERSION.dll (1)<br />LDR: Refcount USERENV.dll (1)<br />LDR: Refcount UxTheme.dll (1)<br />[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0<br />[1cb0,1cac] C:\WINDOWS\AppPatch\AcGenral.DLL init routine 6F8A5E1A<br />[1cb0,1cac] LDR: AcGenral.DLL loaded - Calling init routine at 6F8A5E1A<br />LDR: LdrGetDllHandle, searching for kernel32.dll from<br />LDR: LdrGetProcedureAddress by NAME - InitializeCriticalSectionAndSpinCount<br />LDR: LdrGetProcedureAddress by NAME - GetHookAPIs<br />[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0<br />[1cb0,1cac] C:\WINDOWS\system32\Secur32.dll init routine 77FE2131<br />[1cb0,1cac] C:\WINDOWS\system32\RPCRT4.dll init routine 77E7628F<br />[1cb0,1cac] C:\WINDOWS\system32\ADVAPI32.dll init routine 77DD70D4<br />[1cb0,1cac] C:\WINDOWS\system32\USER32.dll init routine 7E42E966<br />[1cb0,1cac] C:\WINDOWS\system32\GDI32.dll init routine 77F16587<br />[1cb0,1cac] C:\WINDOWS\system32\msvcrt.dll init routine 77C1F2A1<br />[1cb0,1cac] C:\WINDOWS\system32\SHLWAPI.dll init routine 77F651FB<br />[1cb0,1cac] C:\WINDOWS\system32\SHELL32.dll init routine 7C9E7376<br />[1cb0,1cac] c:\WINDOWS\system32\WINMM.dll init routine 76B42B69<br />[1cb0,1cac] C:\WINDOWS\system32\ole32.dll init routine 774FD0A1<br />[1cb0,1cac] C:\WINDOWS\system32\OLEAUT32.dll init routine 77121558<br />[1cb0,1cac] c:\WINDOWS\system32\MSACM32.dll init routine 77BE1292<br />[1cb0,1cac] C:\WINDOWS\system32\VERSION.dll init routine 77C01135<br />[1cb0,1cac] C:\WINDOWS\system32\USERENV.dll init routine 769C15D4<br />[1cb0,1cac] c:\WINDOWS\system32\UxTheme.dll init routine 5AD71626<br />[1cb0,1cac] LDR: Secur32.dll loaded - Calling init routine at 77FE2131<br />[1cb0,1cac] LDR: RPCRT4.dll loaded - Calling init routine at 77E7628F<br />[1cb0,1cac] LDR: ADVAPI32.dll loaded - Calling init routine at 77DD70D4<br />[1cb0,1cac] LDR: USER32.dll loaded - Calling init routine at 7E42E966<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;<br />]LDR: LdrLoadDll, loading C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;<br />]LDR: Loading (DYNAMIC, NON_REDIRECTED) C:\WINDOWS\system32\IMM32.DLL<br />Loaded 'C:\WINDOWS\system32\imm32.dll', no matching symbolic information found.<br />LDR: IMM32.DLL bound to USER32.dll<br />LDR: IMM32.DLL has stale binding to USER32.dll<br />LDR: Stale Bind USER32.dll from IMM32.DLL<br />LDR: IMM32.DLL bound to ntdll.dll<br />LDR: IMM32.DLL has correct binding to ntdll.dll<br />LDR: IMM32.DLL bound to KERNEL32.dll<br />LDR: IMM32.DLL has stale binding to KERNEL32.dll<br />LDR: IMM32.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: IMM32.DLL has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from IMM32.DLL<br />LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error<br />LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap<br />LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap<br />LDR: IMM32.DLL bound to GDI32.dll<br />LDR: IMM32.DLL has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from IMM32.DLL<br />LDR: IMM32.DLL bound to ADVAPI32.dll<br />LDR: IMM32.DLL has correct binding to ADVAPI32.dll<br />[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0<br />[1cb0,1cac] C:\WINDOWS\system32\IMM32.DLL init routine 763912C0<br />[1cb0,1cac] LDR: IMM32.DLL loaded - Calling init routine at 763912C0<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;<br />]LDR: LdrGetProcedureAddress by NAME - ImmWINNLSEnableIME<br />LDR: LdrGetProcedureAddress by NAME - ImmWINNLSGetEnableStatus<br />LDR: LdrGetProcedureAddress by NAME - ImmSendIMEMessageExW<br />LDR: LdrGetProcedureAddress by NAME - ImmSendIMEMessageExA<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPGetIMEW<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPGetIMEA<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPQueryIMEW<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPQueryIMEA<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPSetIMEW<br />LDR: LdrGetProcedureAddress by NAME - ImmIMPSetIMEA<br />LDR: LdrGetProcedureAddress by NAME - ImmAssociateContext<br />LDR: LdrGetProcedureAddress by NAME - ImmEscapeA<br />LDR: LdrGetProcedureAddress by NAME - ImmEscapeW<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionStringA<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionStringW<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionWindow<br />LDR: LdrGetProcedureAddress by NAME - ImmGetContext<br />LDR: LdrGetProcedureAddress by NAME - ImmGetDefaultIMEWnd<br />LDR: LdrGetProcedureAddress by NAME - ImmIsIME<br />LDR: LdrGetProcedureAddress by NAME - ImmReleaseContext<br />LDR: LdrGetProcedureAddress by NAME - ImmRegisterClient<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionFontW<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionFontA<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionFontW<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionFontA<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionWindow<br />LDR: LdrGetProcedureAddress by NAME - ImmNotifyIME<br />LDR: LdrGetProcedureAddress by NAME - ImmLockIMC<br />LDR: LdrGetProcedureAddress by NAME - ImmUnlockIMC<br />LDR: LdrGetProcedureAddress by NAME - ImmLoadIME<br />LDR: LdrGetProcedureAddress by NAME - ImmSetOpenStatus<br />LDR: LdrGetProcedureAddress by NAME - ImmFreeLayout<br />LDR: LdrGetProcedureAddress by NAME - ImmActivateLayout<br />LDR: LdrGetProcedureAddress by NAME - ImmGetCandidateWindow<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCandidateWindow<br />LDR: LdrGetProcedureAddress by NAME - ImmConfigureIMEW<br />LDR: LdrGetProcedureAddress by NAME - ImmGetConversionStatus<br />LDR: LdrGetProcedureAddress by NAME - ImmSetConversionStatus<br />LDR: LdrGetProcedureAddress by NAME - ImmSetStatusWindowPos<br />LDR: LdrGetProcedureAddress by NAME - ImmGetImeInfoEx<br />LDR: LdrGetProcedureAddress by NAME - ImmLockImeDpi<br />LDR: LdrGetProcedureAddress by NAME - ImmUnlockImeDpi<br />LDR: LdrGetProcedureAddress by NAME - ImmGetOpenStatus<br />LDR: LdrGetProcedureAddress by NAME - ImmSetActiveContext<br />LDR: LdrGetProcedureAddress by NAME - ImmTranslateMessage<br />LDR: LdrGetProcedureAddress by NAME - ImmLoadLayout<br />LDR: LdrGetProcedureAddress by NAME - ImmProcessKey<br />LDR: LdrGetProcedureAddress by NAME - ImmPutImeMenuItemsIntoMappedFile<br />LDR: LdrGetProcedureAddress by NAME - ImmGetProperty<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionStringA<br />LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionStringW<br />LDR: LdrGetProcedureAddress by NAME - ImmEnumInputContext<br />LDR: LdrGetProcedureAddress by NAME - ImmSystemHandler<br />LDR: LdrGetProcedureAddress by NAME - CtfImmTIMActivate<br />LDR: LdrGetProcedureAddress by NAME - CtfImmRestoreToolbarWnd<br />LDR: LdrGetProcedureAddress by NAME - CtfImmHideToolbarWnd<br />LDR: LdrGetProcedureAddress by NAME - CtfImmDispatchDefImeMessage<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from<br />LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;<br />]LDR: LdrLoadDll, loading LPK.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;<br />]LDR: Loading (DYNAMIC, NON_REDIRECTED) c:\WINDOWS\system32\LPK.DLL<br />Loaded 'C:\WINDOWS\system32\lpk.dll', no matching symbolic information found.<br />LDR: LPK.DLL bound to ntdll.dll<br />LDR: LPK.DLL has correct binding to ntdll.dll<br />LDR: LPK.DLL bound to KERNEL32.dll<br />LDR: LPK.DLL has stale binding to KERNEL32.dll<br />LDR: LPK.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll<br />LDR: LPK.DLL has correct binding to ntdll.dll<br />LDR: Stale Bind KERNEL32.dll from LPK.DLL<br />LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection<br />LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection<br />LDR: LPK.DLL bound to GDI32.dll<br />LDR: LPK.DLL has stale binding to GDI32.dll<br />LDR: Stale Bind GDI32.dll from LPK.DLL<br />LDR: LPK.DLL bound to USER32.dll<br />NAME - GetThemeInt<br />LDR: LdrGetProcedureAddress by NAME - DrawThemeBackground<br />LDR: LdrGetProcedureAddress by NAME - IsThemeBackgroundPartiallyTransparent<br />LDR: LdrGetProcedureAddress by NAME - GetThemePartSize<br />LDR: LdrGetProcedureAddress by NAME - GetThemeBackgroundContentRect<br />LDR: LdrGetProcedureAddress by NAME - DrawThemeText<br />LDR: LdrGetProcedureAddress by NAME - DrawThemeParentBackground</span></p></div><p>Optionally we can set the flag under the <em>"HLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"</em> by adding a key in the name of the exe for which you want to show Loader information and then adding the "GlobalFlag" under it.( This is the easiest way because you needn't to restart your machine in this case. )<br /><br />Here I mentioned only one value that can be set to the "GlobalFlag". To see the other possible values see <a href="http://support.microsoft.com/kb/147314">GlobalFlags for Windows</a> . </p>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com1tag:blogger.com,1999:blog-8614819832544366718.post-5756928519307516482008-04-17T02:55:00.000-07:002009-04-07T09:28:15.076-07:00Pointer pointing to Stack or Heap ??<div align="justify">Today on Code project some one posted a question like "Is there any way to find whether a pointer points to stack or heap". Is there actually an API for the same??<br /><br />Well windows dosen't provide an API or a straight forward way to acomplish this. Any how we can find a pointer points to stack or heap by simple computations and ofcourse with the help of TIB( Thread Infomation Block - If you want to learn more about TIB, have a look to the <a href="http://www.microsoft.com/msj/archive/S2CE.aspx">Under The Hood</a> article of Matt Pietrek ). In the Thread information block, there are two members, the "StackTop"( located at FS[4] ) and "StackBase" ( located at FS[8] ). The "StackTop" is the memory from which the stack started, and the "StackBase" is the stack location the program commits upto that point. So any object created on stack will have an address between this two pointers. So if we get a pointer just check whether the pointer falls between the above two memory locations. if it does, then it can be consider a pointer to some stack object. So here is my API to find whether the pointer points to stack or heap.<br /></div><br /><div align="justify">// This function will return <em>true</em> if the pointer points to stack. Other wise <em>false</em></div><div align="justify"><span style="color:#ff6600;">bool IsMemoryOnStack( LPVOID pVoid )<br />{<br />LPVOID dwStackTop = 0;<br />LPVOID dwStackLowCurrent = 0;<br />__asm<br />{<br />mov EAX, FS:[4]<br />mov dwStackTop, eax<br />mov EAX, FS:[8]<br />mov dwStackLowCurrent, eax<br />}<br />if( pVoid <= dwStackTop && pVoid >= dwStackLowCurrent )<br />{</span></div><div align="justify"><span style="color:#ff6600;">// The memory lie between the stack top and stack commited.<br />return true;<br />}</span></div><div align="justify"><span style="color:#ff6600;">// Pointer dosen't point to the stack<br />return false;<br />}</span></div><div align="justify"><span style="color:#ff6600;"><span style="font-size:0;"></span></span></div><br /><div align="justify"><span>Sample code that uses the above API..<br /><br /><span style="color:#ff9900;">void main()<br />{<br />int OnStack;<br />bool bOnStack = IsMemoryOnStack( &OnStack );// Returns true<br />int *pOnHeap = new int;<br />bOnStack = IsMemoryOnStack( pOnHeap );// Returns false<br />}</span></span></div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com4tag:blogger.com,1999:blog-8614819832544366718.post-73148603668364003092008-04-16T02:25:00.000-07:002009-04-07T09:28:15.076-07:00Break application on dll Load<div align="justify">What will you do if you encounter a crash in an application before it reaches the entry point ok exe. I. e the crach happends before the control reaches the WinMain. In such cases the crash might have happened in the dll loaded by the exe. To be more specific say in the <span style="color:#ff6600;">DllMain()</span> of dlls. In most cases we will not be having the source code of all dll so that we can put some breakpoint in the <span style="color:#ff6600;">DllMain()</span> and debug. So how to track which dll is causing the problem...</div><div align="justify"></div><div align="justify">The windows loader provids an option to break the debugee while loading dlls. For this we have to set appropriate values under "<em><span style="color:#ff6600;">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options</span></em>" key.</div><br /><div align="justify">Suppose I have a application which have dependency with "Foo.dll" and I want the bebugger to break just before loading "Foo.dll". To do so create a key under the "Image File Execution Options" like</div><div align="justify"></div><div align="left"><em>"<span style="color:#ff6600;">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Foo.dll</span>"</em>.</div><div align="justify"></div><div align="justify"></div><div align="justify"> </div><div align="justify">Add a <span style="font-size:+0;">DWORD </span>value under this key with name "<em>BreakOnDllLoad</em>" and set its value as one. </div><p align="justify">Now if you start the application from the debugger. The debugeer will report a breakpoint hit during startup. This break point will be just above the call to Dll entry point of foo.dll.( The entry point is<span style="color:#ff6600;">_DllMainCRTStartup</span> if the dll is written using vc++. This function later calls <span style="color:#ff6600;">DllMain</span><span style="color:#ff6600;">()</span>)<br /><br /></p><p align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoeG_3rMZCnzPdjtkiTFTxTJwz4KhJHjrnNR4n-sRdpVcFwW3Z5tx-BJpJ3prK_AKJYlCzeJl7hRVlGbu0Rk-M9dyH6OK2XR4hAgyWgOPAVq4beQXf1epJKQ7ES37ijTEMWM5wF4Xl6Gg/s1600-h/breakonload.JPG"><img id="BLOGGER_PHOTO_ID_5189783011893412610" style="CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoeG_3rMZCnzPdjtkiTFTxTJwz4KhJHjrnNR4n-sRdpVcFwW3Z5tx-BJpJ3prK_AKJYlCzeJl7hRVlGbu0Rk-M9dyH6OK2XR4hAgyWgOPAVq4beQXf1epJKQ7ES37ijTEMWM5wF4Xl6Gg/s400/breakonload.JPG" border="0" /></a></p><br /><p align="left"></p>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-92058842536431558672008-04-15T00:46:00.000-07:002009-04-07T09:28:15.076-07:00__asm int 3 in template function ( in VC6 )We usually use <em>__asm int 3</em> in the code to hard code break points. But have you tried setting a <em>__asm int 3</em> in a template function? Like...<br /><br /><span style="color:#ff6600;">template<</>class T</>> int Testfunc( T Obj )</span><br /><span style="color:#ff6600;">{</span><br /><span style="color:#ff6600;">__asm int 3;</span><br /><span style="color:#ff6600;">return Obj++;</span><br /><span style="color:#ff6600;">}<br /></span><br /><span style="color:#ff6600;">void main()</span><br /><span style="color:#ff6600;">{</span><br /><span style="color:#ff6600;">Testfunc( 1 );</span><br /><span style="color:#ff6600;">};</span><br /><br /><span>The above code will never get compiled in vc6. It will generate the below error <span><br /><em></em></span></span><br /><span><span><em>"fatal error C1001: INTERNAL COMPILER ERROR<br />(compiler file 'msc1.cpp', line 1794)<br />Please choose the Technical Support command on the Visual C++ Help menu, or open the Technical Support help file for more information<br />Generating Code...Command line warning D4028 : minimal rebuild failure, reverting to normal build<br />Error executing cl.exe."<br /></em><br />But the same code will compile fine in later versions of visual studio. Seems they have fixed the bug :)</span></span>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-69748929101996653092008-04-14T17:29:00.000-07:002009-04-07T09:28:15.077-07:00MessageBox in ExitInstanceLike the problem in displaying the message box in InitInstance of an APP class, there is a problem in displaying the message box in <span style="color:#ff6600;">ExitInstance()</span> also. Try the following code..<br /><br /><span style="color:#ff6600;">int CMyApp::ExitInstance() </span><br /><span style="color:#ff6600;">{</span><br /><span style="color:#ff6600;">AfxMessageBox( "Some message from CMyApp::ExitInstance" );</span><br /><span style="color:#ff6600;">return CWinApp::ExitInstance();</span><br /><span style="color:#ff6600;">}</span><br /><br /><div align="justify">The messagebox will never appear!!!! After a small investigation, I found that this is beacuse of the <span style="color:#ff6600;">WM_QUIT</span> message that exists in the message queue. So removing the <span style="color:#ff6600;">WM_QUIT</span> message from the message queue will simply solve the problem. For removing the <span style="color:#ff6600;">WM_QUIT</span>, a <span style="color:#ff6600;">GetMessage()</span> function in while loop while be enough. So I modified the code as follows..</div><br /><span style="color:#ff6600;">int CMyApp::ExitInstance()</span><br /><span style="color:#ff6600;">{</span><br /><span style="color:#ff6600;">MSG stMsg;</span><br /><span style="color:#ff6600;"></span><span style="color:#ff0000;">while( GetMessage( &stMsg,0,0,0));</span><br /><span style="color:#ff6600;">AfxMessageBox( "Some message from CMyApp::ExitInstance" );</span><br /><span style="color:#ff6600;">return CWinApp::ExitInstance();</span><br /><span style="color:#ff6600;">}</span><br /><br /><div align="justify"></div><div align="justify">After this the message box is showing correctly. The Theory is that, when we try to create a window and at that time if a <span style="color:#ff6600;">WM_QUIT</span> message exists in the message queue, the window creation will fail. Putting the <span style="color:#ff6600;">GetMessage</span> in the while loop will remove the <span style="color:#ff6600;">WM_QUIT</span> from the message loop also <span style="color:#ff6600;">GetMessage</span> will return false if it encounters a <span style="color:#ff6600;">WM_QUIT</span>. Thus it exits from the while loop.</div><br /><div align="justify">Though we got a soltion, did you thought who send the <span style="color:#ff6600;">WM_QUIT</span> message? The <span style="color:#ff6600;">WM_QUIT</span> message is normally created using the <span style="color:#ff6600;">PostQuitMessage()</span> and in MFC <span style="color:#ff6600;">AfxPostQuitMessage()</span> function wrappers <span style="color:#ff6600;">PostQuitMessage().</span> So I put a breakpoint in <span style="color:#ff6600;">AfxPostQuitMessage()</span> and waited. Upon clicking the Close button in the dialog, the break point triggered. And the callstack window shows that the <span style="color:#ff6600;">CWnd::OnNcDestroy()</span> function called <span style="color:#ff6600;">AfxPostQuitMessage().</span></div><br /><p><img id="BLOGGER_PHOTO_ID_5189271674561987282" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUz7AtC3Z8NFUl-nBqvIBWKwP-R2co3jruaierk-pnTI0pVgc3ZBcx969DCiyNdncGo6HF3eNuBEwm0FiV9kx_RaOUGKoONL-1OkkdIVgjZ1gfd8uAwVxm-0UhongBJ5R2Y67I-WMNqkM/s400/CallStack.JPG" border="0" /></p><p align="justify">If you check the <span style="color:#ff6600;">CWnd::OnNcDestroy()</span> function, you can find that, it calls the <span style="color:#ff6600;">AfxPostQuitMessage</span> upon checking various conditions such as The window closed now is a Main Window, The Current instance is not a dll etc..</p>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-74948074984274667452008-04-07T18:52:00.000-07:002009-04-07T09:28:15.077-07:00When a MessageBox in InitInstance didn't show..Once I created one utility in which had the below piece of code.<br /><br /><br /><span style="color:#ff6600;">BOOL CMyApp::InitInstance()</span><br /><span style="color:#ff6600;">{<br /></span><br /><span style="color:#ff6600;">AfxEnableControlContainer(); </span><br /><span style="color:#ff6600;">#ifdef _AFXDLL </span><br /><span style="color:#ff6600;">Enable3dControls(); </span><br /><span style="color:#ff6600;">#else </span><br /><span style="color:#ff6600;">Enable3dControlsStatic(); </span><br /><span style="color:#ff6600;">#endif </span><br /><span style="color:#ff6600;">HANDLE hMutex = CreateMutex( 0, 0, _T("Some_Mutex")); </span><br /><span style="color:#ff6600;">if( GetLastError() == ERROR_ALREADY_EXISTS ) </span><br /><span style="color:#ff6600;">{ </span><br /><span style="color:#ff6600;">AfxMessageBox( _T("Only one instance of the application can be run")); </span><br /><span style="color:#ff6600;">CloseHandle( hMutex ); </span><br /><span style="color:#ff6600;">return FALSE; </span><br /><span style="color:#ff6600;">}</span><br /><span style="color:#ff6600;">CMyDlg dlg;</span><br /><span style="color:#ff6600;">m_pMainWnd = &dlg; </span><br /><span style="color:#ff6600;">int nResponse = dlg.DoModal(); </span><br /><span style="color:#ff6600;">CloseHandle( hMutex ); </span><br /><span style="color:#ff6600;">return FALSE;</span><br /><span style="color:#ff6600;">}</span><br /><br /><br /><div align="justify">My purpose was to run only one instance of the application. If more than one instance is run, the second instance will show a message box and exits. Before release of the utility, I some touch ups in the application. Fortunately just before the release I noticed that, if two instance of the application is run, the second instance simply exits without showing that message box. </div><div align="justify"></div><div align="justify"></div><div align="justify">Then I started to roll back the touch ups one by one. After removing one of them, the message box again showed. And that touch up was the manifest file I added for giving XP look and feel. I searched and searched and finally found out that the problem is because of not calling the InitCommonControls() function. It was right there in the documentation <a><a href="http://msdn2.microsoft.com/en-us/library/ms997646.aspx">Using Windows XP Visual Styles</a>[<a title="New Window" href="http://msdn2.microsoft.com/en-us/library/ms997646.aspx" target="_blank">^</a>]</a> , but I never followed it. </div><br /><br /><div align="justify">The actual purpose of the <span style="color:#cc6600;">InitCommonControls</span>() is described in <a href="http://blogs.msdn.com/oldnewthing/archive/2005/07/18/439939.aspx">The Old New Thing</a> [<a title="New Window" href="http://blogs.msdn.com/oldnewthing/archive/2005/07/18/439939.aspx" target="_blank">^</a>]. It says if we didn't call the <span style="color:#cc6600;">InitCommonControls</span>() funtion, our application will not be having any reference to the <span style="color:#ff6600;">COMCTL32.DLL</span> and therefore will not be loaded while my application start. So when I tries to create a window, the class will not be registered and so the <span style="color:#ff6600;">CreateWindow</span>() function will fail.<br /></div><br /><br /><br /><div align="justify">How ever my doubt was, even with out the <span style="color:#cc6600;">InitCommonControls</span>() function, my application dialog was showing correctly. Only the Message box had the problem. <span style="color:#cc6600;">InitCommonControls</span>() isn't necessary for the dialog? How ever when I stepped into the source code of the MFC, things became clear. Inside the <span style="color:#cc6600;">DoModal</span>() function, it is calling the <span style="color:#cc6600;">InitCommonControls</span>(). The <span style="color:#cc6600;">AfxDeferRegi</span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSXqPY7bP9xkHRDM_SoGsBpEcadZEh_T7mMBmkCidCvkeMU1tTGSnrieDGROzIDbyZtHPfiAxJFLBLIahnvjNpdl1q4KYBB-9PAuw5YVvds0358ubtQTqv550bP89Qy0aiaGsFYKv-0TE/s1600-h/peview.JPG"><span style="color:#cc6600;"></span></a><span style="color:#cc6600;">sterClass</span> MACRO was doing this job.<br /></div><br /><br /><div align="justify">Now I got another doubt, Since MFC calls the <span style="color:#cc6600;">InitCommonControls</span>() function, the <span style="color:#ff6600;">COMCTL32.DLL</span> will be statically linked to <span style="color:#ff6600;">MFC42.dll</span> and my application is statically linked to the <span style="color:#ff6600;">MFC42.dll</span>. So <span style="color:#ff6600;">COMCTL32.DLL</span> should definitly load in the beginning itself. But for some reasons even though <span style="color:#ff6600;">MFC42.dll</span> was loaded, <span style="color:#ff6600;">COMCTL32</span>.<span style="color:#ff6600;">DLL</span> didn't get loaded. </div><br /><br /><div align="justify">The only possibility for such a scenario will be a delay load of <span style="color:#ff6600;">COMCTL32.DLL</span> in the <span style="color:#ff6600;">MFC42.dll</span> dll. To confirm, I opened the <span style="color:#ff6600;">MFC42.dll</span> in PEView. As expected the <span style="color:#ff6600;">COMCTL32.DLL</span> was added in the "DELAY IMPORT Address Table". </div><br /><br /><br /><img id="BLOGGER_PHOTO_ID_5187927829821022274" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 549px; CURSOR: hand; HEIGHT: 387px; TEXT-ALIGN: center" height="461" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQKLaXOqHBZAs5uG699_P06dO3moIi5s-J-DV5QOyu0WAYF2l3dFqcnwyoM_W3nifQBMknP1-EfpkugyubaV653oK_CPLsGEcpdQbyfqtJ5Fl73qMAsK0m8hQkH9S8hCmyURxYm0gZafc/s400/peview.JPG" width="495" border="0" /><br /><br /><br /><div align="justify">Let look back to the original problem. "Message box got displayed in normal case even if I didn't call the <span style="color:#ff6600;">InitCommonControls</span>()" . So <span style="color:#ff6600;">COMCTL32.DLL</span> not need if didn't use manifest?? The answer is no. In windows Some window classes are register by <span style="color:#ff6600;">User32.dll</span>( Like button, edit etc ) and some other control( Windows common controls ) are registered by <span style="color:#ff6600;">COMCTL32.DLL</span>. But if we add manifest files, <span style="color:#ff6600;">user32.dll</span> will not be registering any of the window classes instead <span style="color:#ff6600;">COMCTL32.DLL</span> will do all the registrations. If you check the manifest file of the <span style="color:#ff6600;">COMCTL32.DLL</span> version 6, you can see the list of window classes versioned in it. </div><br /><div align="justify"></div><div align="justify">( The file is located in "C:\WINDOWS\WinSxS\Manifests\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.0.0_x-ww_1382d70a.Manifest" )</div><br /><div align="justify"></div>So to conclude, what I learned because of message box problem are.<br /><br /><br />1. Whether or not you are using Manifest file, you should call <span style="color:#ff6600;">InitCommonControls</span>() or <span style="color:#ff6600;">InitCommonControlsEx</span>().<br /><br />2. <span style="color:#ff6600;">MFC42.dll</span> have set <span style="color:#ff6600;">COMCTL32.DLL</span> to delay load. ( But when I checked in <span style="color:#ff6600;">MFC8.dll</span>, the delayed loading of <span style="color:#ff6600;">COMCTL32</span> is removed )<br /><br />3. If we use manifest file, <span style="color:#ff6600;">COMCTL32.DLL</span> will doing the registration of all System Classes instead of user32.dll. So it is necessary to ensure that <span style="color:#ff6600;">COMCTL32.DLL</span> have loaded before you create a window belonging to system class.Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-59736680704197993722008-03-23T05:12:00.000-07:002009-04-07T09:28:15.077-07:00Find which dll / exe created a window.<div align="left">The <span style="color:#ff6600;">GetWindowModuleFileName()</span> functions can be used to find which exe or dll have created a window. But the problem with this function is that, it will not work across process.<br /><br />When ever we create a window, we have to pass the an <span style="color:#ff6600;">HINSTANCE</span> into it. And later we can use <span style="color:#ff6600;">GetWindowLong</span> to get that <span style="color:#ff6600;">HINSTANCE</span>. Actually the <span style="color:#ff6600;">HINSTANCE </span>is noting but the <span style="color:#ff6600;">HMODULE</span> itself. So if we get the hinstance of a window, we can pass this handle to the<br /><span style="color:#ff6600;">GetModuleFileNameEx()</span> and simply get the name of the window from other processes also.<br /><br /><br /><span style="color:#cc6600;">CString MyGetWindowModuleFileName( HANDLE hwindowhandle )<br />{<br />CString csModuleName;<br />DWORD dwProcessId;<br />GetWindowThreadProcessId( hwindowhandle, &dwProcessId );<br />HINSTANCEhModule = (HINSTANCE)GetWindowLong( hwindowhandle, GWL_HINSTANCE );<br />if(hModule == NULL)<br />{<br />return csModuleName;<br />}<br />HANDLE hProcess = OpenProcess(PROCESS_VM_READPROCESS_QUERY_INFORMATION, FALSE, dwProcessId );<br />if( hProcess == NULL )<br />{<br />return csModuleName;<br />}<br />BOOL bReturn = GetModuleFileNameEx( hProcess, hModule, csModuleName.GetBuffer( MAX_PATH), MAX_PATH );<br />csModuleName.ReleaseBuffer();<br />CloseHandle(hProcess);<br />return csModuleName;<br />}</span></div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-62402671779498493402008-01-03T08:38:00.000-08:002009-04-07T09:28:15.077-07:00WM_DEVICECHANGE problem<div align="justify">In one our Projects at company, we used <span style="color:#cc6600;">WM_DEVICECHANGE</span> message to detect the arrival and removal of USB devices. The application was supposed to run on a machine in which will be running along with several other utility applications. Some months after the project delivery, client reported that, sometimes even if a USB device is plugged in, it is not detected. Problem problem.....<br /><br />After some investigations we found that if we make the window a top-level window (<span style="color:#cc6600;">HWND_TOPMOST</span>), there is no such problems. But what’s the relation between the z-order and the above problem. Later we got few more points to identify the relation.<br /><br />1. The <span style="color:#ff6600;">WM_DEVICECHANGE</span> is send to all the top-level windows according to their z-order. That is the window at the top most position receives the message first, then only the window below it and so one.<br /></div><div align="justify">2. If a window got a <span style="color:#cc0000;">WM_DEVICECHANGE</span> and if it didn’t process the message with in a period (in my machine I think it was 20 secs), the message will not reach to the subsequent windows under it.<br /><br />Now everything became clear to us, some window whose z-order is greater than our application window might have hung or didn’t process the message within 20 seconds. Thus our window didn’t get a chance. Also when we made our window top level it will be one of the first window's to get <span style="color:#ff6600;">WM_DEVICECHANGE</span> message so reducing the number of windows above it to get hung. How ever we didn't find a proper solution for this and moved to an alternative method to detect device arrival and removal.<br /><br />I think windows might not be using the <span style="color:#ff6600;">BroadcastSystemMessage()</span> function with the <span style="color:#cc6600;">BSF_FORCEIFHUNG</span> flag, while sending the <span style="color:#cc6600;">WM_DEVICECHANGE</span> message.</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com1tag:blogger.com,1999:blog-8614819832544366718.post-24094421442260336572007-10-31T09:34:00.000-07:002009-04-07T09:28:15.077-07:00Bug in Rich Edit controlBasically this not a vc++ bug. Its actually a bug in the RichEdit control so the bug belongs to windows.<br /><br />Check the picture...<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0ZoMTuEQ8mLsMm6LTVf3387MAJSOZkrkacixhACVpFod6RTi5fLpwNE1H2c-Qci64gvGjPDgqUyY_fsdHkRtMZgsZjolaTYxckS3z29wBpBF2iK6baKw_Wx6E0iQ5PtC9BlaOyOuYXDQ/s1600-h/richedit.JPG"><img id="BLOGGER_PHOTO_ID_5127767625425905010" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0ZoMTuEQ8mLsMm6LTVf3387MAJSOZkrkacixhACVpFod6RTi5fLpwNE1H2c-Qci64gvGjPDgqUyY_fsdHkRtMZgsZjolaTYxckS3z29wBpBF2iK6baKw_Wx6E0iQ5PtC9BlaOyOuYXDQ/s320/richedit.JPG" border="0" /></a> <div>What you see inside the red circle is the caret of rich edit control. It passed the boundaries of rich edit control and moved to the dialog.<br /><br />Step to reproduce.<br /><br />1. Create a dialog based application and place a rich edit control on it.<br />2. Give the Multi line and Auto HSCROLL style.<br />3. Now run the application and click inside the rich edit, and keep on pressing space bar. You can see the caret crossing the boundary of rich edit and starts moving through the dialog.</div><div> </div><div>This problem exists in vista and XP. But I didn't find a place to report this bug to Microsoft. I searched the whole internet to find some one already reported this problem. But coudn't find any. I dont know why such a problem haven't been noticed for the past 12 years( 12 years because I think the problem exists in the rich edit of 95 also ).</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com0tag:blogger.com,1999:blog-8614819832544366718.post-15666710760165283272007-10-30T05:36:00.000-07:002009-04-07T09:47:48.598-07:00Hide / Minimize dialog on startup<div align="justify">Have you ever tried to minimize a dialog during the startup of a dialog based application? The problem is in a dialog based application, we will not get the control after the dialog is completely created. Even a call to <span style="color:#cc6600;">ShowWindow()</span> from the <span style="color:#cc6600;">OnInitDialog()</span> function, will not work. So what will we do if we got such a requriment? Well I got a simple technique for doing this by modifying the <span style="color:#cc6600;">InitInstance()</span> function of the app class.<br /><br />The code for creating a dialog in the <span style="color:#cc6600;">InitInstance()</span> function will look like this.<br /><br /><span style="color:#cc6600;">CDialogBasedDlg dlg;</span><br /><span style="color:#cc6600;">m_pMainWnd = &dlg;</span><br /><span style="color:#cc6600;">INT_PTR nResponse = dlg.DoModal();</span><br /><br />My idea is to change this code a little as follows..<br /><br /><span style="color:#cc6600;">CDialogBasedDlg dlg;</span><br /><span style="color:#cc6600;">if(dlg.Create( CDialogBasedDlg::IDD ))</span> </div><div align="justify"><span style="color:#cc6600;"><pre>{<br /> dlg.ShowWindow( SW_HIDE );<br /> m_pMainWnd = &dlg;<br /> INT_PTR nResponse = dlg.RunModalLoop();<br />}</pre></span><br /><br />Actually inside the MFC framework, the DoModal() function calls the <span style="color:#cc6600;">CreateDlgIndirect()</span> and then <span style="color:#cc6600;">RunModalLoop()</span>. It also handles the tasks such as disabling the parent window etc. In our case the dialog itself is the parent window so do haven't to worry about such things.</div>Naveenhttp://www.blogger.com/profile/11819187329082113372noreply@blogger.com1