<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rubato and Chord</title><link>http://blogs.msdn.com/b/reiley/</link><description>Reiley&amp;#39;s technical blog</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>Vector Deleting Destructor</title><link>http://blogs.msdn.com/b/reiley/archive/2013/05/09/vector-deleting-destructor.aspx</link><pubDate>Thu, 09 May 2013 14:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10417325</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10417325</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2013/05/09/vector-deleting-destructor.aspx#comments</comments><description>&lt;p&gt;Today one guy in my team asked a question regarding the behavior of delete[] operator in C++&amp;nbsp;- how does the program know it needs to call &lt;span style="font-family: verdana,geneva;"&gt;CBar::~CBar&lt;/span&gt; instead of &lt;span style="font-family: verdana,geneva;"&gt;CFoo::~CFoo&lt;/span&gt;?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that the vector deleting destructor is a feature in Microsoft C++ Compiler,&amp;nbsp;not&amp;nbsp;required by&amp;nbsp;the C++ standard.&lt;/em&gt;&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;#define&lt;/span&gt;&amp;nbsp;&lt;span style="color: #6f008a;"&gt;_CRTDBG_MAP_ALLOC&lt;/span&gt;
&lt;span style="color: blue;"&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;&amp;lt;malloc.h&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;&amp;lt;crtdbg.h&amp;gt;&lt;/span&gt;

&lt;span style="color: blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;CFoo&lt;/span&gt;
{
&lt;span style="color: blue;"&gt;public&lt;/span&gt;:
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;virtual&lt;/span&gt;&amp;nbsp;~CFoo()&amp;nbsp;=&amp;nbsp;0;
};

&lt;span style="color: blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;CBar&lt;/span&gt;
{
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;virtual&lt;/span&gt;&amp;nbsp;~CBar()
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #6f008a;"&gt;_CrtDbgBreak&lt;/span&gt;();
&amp;nbsp;&amp;nbsp;}
};

&lt;span style="color: blue;"&gt;void&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;__cdecl&lt;/span&gt;&amp;nbsp;main()
{
&amp;nbsp;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;CBar&lt;/span&gt;*&amp;nbsp;p&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;CBar&lt;/span&gt;[1];
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;delete&lt;/span&gt;[]&amp;nbsp;(&lt;span style="color: #2b91af;"&gt;CFoo&lt;/span&gt;*)p;&amp;nbsp;&lt;span style="color: green;"&gt;//&amp;nbsp;what&amp;nbsp;does&amp;nbsp;this&amp;nbsp;mean?&lt;/span&gt;
&amp;nbsp;&amp;nbsp;_CrtDumpMemoryLeaks();
}&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;Well the short answer would be - how does virtual destructor work and how does the program know the actual number of elements in the array?&lt;/p&gt;
&lt;p&gt;If you've spent time on understanding the object layout in C++ and COM, you would know that virtual functions are backed by &lt;strong&gt;&lt;em&gt;vtable&lt;/em&gt;&lt;/strong&gt;, and it will not be too difficult to understand &lt;a title="BSTR" href="http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx" target="_blank"&gt;BSTR&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So we are ready for the answer - &lt;strong&gt;delete[] is a combination of BSTR and virtual function&lt;/strong&gt;.&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;CBar::`vector deleting destructor':
000007F7CD2E1140  mov         dword ptr [rsp+10h],edx  
000007F7CD2E1144  mov         qword ptr [rsp+8],rcx  
000007F7CD2E1149  sub         rsp,28h  
000007F7CD2E114D  mov         eax,dword ptr [rsp+38h]  
&lt;span style="color: #ff00ff;"&gt;000007F7CD2E1151 and eax,2&lt;br /&gt;000007F7CD2E1154 test eax,eax&lt;br /&gt;000007F7CD2E1156 je CBar::`vector deleting destructor'+5Eh (07F7CD2E119Eh)&lt;/span&gt;  
000007F7CD2E1158  lea         &lt;span style="color: #ff0000;"&gt;r9&lt;/span&gt;,[CBar::~CBar (07F7CD2E1120h)] &lt;span style="color: #0000ff;"&gt;; the address of CBar::~CBar&lt;/span&gt; 
000007F7CD2E115F  mov         rax,qword ptr [this]             &lt;span style="color: #0000ff;"&gt;; this pointer&lt;/span&gt;  
000007F7CD2E1164  mov         &lt;span style="color: #ff0000;"&gt;r8d&lt;/span&gt;,dword ptr [rax-8]            &lt;span style="color: #0000ff;"&gt;; array size *((size_t*)this - 1)&lt;/span&gt;  
000007F7CD2E1168  mov         &lt;span style="color: #ff0000;"&gt;edx&lt;/span&gt;,8                            &lt;span style="color: #0000ff;"&gt;; sizeof(CBar)&lt;/span&gt;  
000007F7CD2E116D  mov         &lt;span style="color: #ff0000;"&gt;rcx&lt;/span&gt;,qword ptr [this]             &lt;span style="color: #0000ff;"&gt;; this pointer&lt;/span&gt;  
000007F7CD2E1172  call        `&lt;span style="color: #0000ff;"&gt;vector destructor iterator&lt;/span&gt;' (07F7CD2E1220h)  
&lt;/pre&gt;
&lt;p&gt;As you can see here, the &lt;strong&gt;vector deleting destructor&lt;/strong&gt; was emitted as a virtual function in &lt;strong&gt;vtable&lt;/strong&gt;, it takes a flag parameter, if &lt;span style="font-family: verdana,geneva;"&gt;flag &amp;amp; 0x2&lt;/span&gt; equals to true, the actual function &lt;strong&gt;vector destructor iterator&lt;/strong&gt; would get called.&lt;/p&gt;
&lt;p&gt;The size of array was stored using the BSTR approach, passed in via the &lt;strong&gt;r8d&lt;/strong&gt; register.&lt;/p&gt;
&lt;p&gt;The callstack from Visual Studio Debugger also tells us the same thing:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;crtdbg.exe!&lt;span style="color: #ff00ff;"&gt;`vector destructor iterator'(void * __t, unsigned __int64 __s, int __n, void (void *) * __f)&lt;/span&gt;	C++
crtdbg.exe!&lt;span style="color: #ff00ff;"&gt;CBar::`vector deleting destructor'(unsigned int)&lt;/span&gt;	C++
crtdbg.exe!main() Line 22	C++
crtdbg.exe!__tmainCRTStartup() Line 536	C
crtdbg.exe!mainCRTStartup() Line 377	C
kernel32.dll!BaseThreadInitThunk&#x1E;()	Unknown
ntdll.dll!RtlUserThreadStart()	Unknown
&lt;/pre&gt;
&lt;p&gt;Regarding the actual meaning of the flag I mentioned, I'll leave it as a homework for the readers (hint: you may try out the &lt;a title="DGML" href="http://blogs.msdn.com/b/reiley/archive/2012/08/19/visualize-assembly-using-dgml.aspx" target="_blank"&gt;DGML&lt;/a&gt; tool).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10417325" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Visual+Studio/">Visual Studio</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/C_2B002B00_/">C++</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/CRT/">CRT</category></item><item><title>Undocumented Environment Variables</title><link>http://blogs.msdn.com/b/reiley/archive/2013/05/08/undocumented-environment-variables.aspx</link><pubDate>Wed, 08 May 2013 14:09:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10417019</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10417019</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2013/05/08/undocumented-environment-variables.aspx#comments</comments><description>&lt;p&gt;Although we have less &lt;a title="Easter Eggs" href="http://blogs.msdn.com/b/larryosterman/archive/2005/10/21/483608.aspx" target="_blank"&gt;Easter Eggs&lt;/a&gt;,&amp;nbsp;there are still a huge number of&amp;nbsp;&lt;a title="undocumented behaviors" href="http://blogs.msdn.com/b/reiley/archive/2011/10/30/undocumented-windbg.aspx" target="_blank"&gt;undocumented behaviors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Recently I'm writing&amp;nbsp;a CLR profiler using ICorProfilerCallback for fun, the CLR profiler was modeled as an in-proc COM server, and the activition was done through environment variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SET COR_ENABLE_PROFILING=1&lt;/li&gt;
&lt;li&gt;SET COR_PROFILER={XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}&lt;/li&gt;
&lt;li&gt;SET COR_PROFILER_PATH="C:\FOO\BAR\MyProfiler.dll"&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Immediately I realized there must be a lot more environment variables, and it&amp;nbsp;was a perfect time to use WinDBG:&amp;nbsp;&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="font-family: verdana,geneva; background-color: #c0c0c0;"&gt;cdb.exe -hd -g -G -xi ld -xe cpr -c "bu KERNELBASE!GetEnvironmentVariableW \"du @rcx; gc\"; g" "%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe"&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;0:000&amp;gt; cdb: Reading initial command 'bu KERNELBASE!GetEnvironmentVariableW "du @rcx; gc"; g'
000007fe`581406f0  "&lt;span style="color: #ff0000;"&gt;SHIM_DEBUG_LEVEL&lt;/span&gt;"
000007fe`58140428  "&lt;span style="color: #ff0000;"&gt;SHIM_FILE_LOG&lt;/span&gt;"
000007fe`581406f0  "&lt;span style="color: #ff0000;"&gt;SHIM_DEBUG_LEVEL&lt;/span&gt;"
SHIMVIEW: ShimInfo(Complete)
(ba0.db8): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
000007fe`5c4eada0 cc              int     3
0:000&amp;gt; g
Microsoft (R) Visual C# Compiler version 4.0.30319.17929
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

warning CS2008: No source files specified
000000a3`60e9c230  "&lt;span style="color: #0000ff;"&gt;COMPlus_Version&lt;/span&gt;"
000000a3`60e9c230  "&lt;span style="color: #0000ff;"&gt;COMPlus_InstallRoot&lt;/span&gt;"
000000a3`60e9b790  "COMPlus_InstallRoot"
000000a3`60e9c140  "&lt;span style="color: #0000ff;"&gt;COMPlus_DefaultVersion&lt;/span&gt;"
000000a3`60e9bad0  "COMPlus_InstallRoot"
000000a3`60e9b880  "COMPlus_InstallRoot"
000000a3`60e9b8a0  "&lt;span style="color: #0000ff;"&gt;COMPlus_3gbEatMem&lt;/span&gt;"
000000a3`60e9b400  "&lt;span style="color: #0000ff;"&gt;COMPLUS_CLRLoadLogDir&lt;/span&gt;"
000000a3`60e9b1d0  "COMPlus_InstallRoot"
000000a3`60e9b180  "COMPlus_NicPath"
000000a3`60e9b180  "&lt;span style="color: #0000ff;"&gt;COMPlus_RegistryRoot&lt;/span&gt;"
000000a3`60e9b180  "&lt;span style="color: #0000ff;"&gt;COMPlus_AssemblyPath&lt;/span&gt;"
000000a3`60e9b180  "&lt;span style="color: #0000ff;"&gt;COMPlus_AssemblyPath2&lt;/span&gt;"
000000a3`60e9ab80  "COMPLUS_InstallRoot"
000000a3`60e9ab40  "COMPLUS_DefaultVersion"
000000a3`60e9ab40  "COMPLUS_Version"
000000a3`60e9af60  "COMPLUS_ApplicationMigrationRunt"
000000a3`60e9afa0  "imeActivationConfigPath"
000000a3`60e9afb0  "&lt;span style="color: #0000ff;"&gt;COMPLUS_OnlyUseLatestCLR&lt;/span&gt;"
000007fe`51a06580  "APPX_PROCESS"
000000a3`60e9af60  "COMPLUS_BuildFlavor"
000007f6`2e5c16a8  "LIB"
error CS1562: Outputs without source must have the /out option specified
&lt;/pre&gt;
&lt;p&gt;As we can see, the red parts are the environment variables used by Application Compatibility team for debugging a shim.&lt;/p&gt;
&lt;p&gt;The blue parts are the environment variables used by COMPLUS, which was the original name for .NET.&lt;/p&gt;
&lt;p&gt;Notice that there is guarantee of completeness using my WinDBG approach, since GetEnvironmentVariableW is not the only way to retrieve environment variables.&lt;/p&gt;
&lt;p&gt;I'll leave a homework for the readers - find the envrionment variables consumed by the Visual Studio IDE (hint: you need to modify the command line to make it work under 32bit).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10417019" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Pop+Quiz/">Pop Quiz</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/CLR/">CLR</category></item><item><title>The Pit of Success</title><link>http://blogs.msdn.com/b/reiley/archive/2013/04/27/the-pit-of-success.aspx</link><pubDate>Sat, 27 Apr 2013 14:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10414490</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10414490</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2013/04/27/the-pit-of-success.aspx#comments</comments><description>&lt;p&gt;&lt;span style="color: #000000; font-family: book antiqua,palatino; font-size: medium;"&gt;&lt;em&gt;The Pit of Success: in stark contrast to a summit, a peak, or a journey across a desert to find victory through many trials and surprises, we want our customers to simply fall into winning practices by using our platform and frameworks. To the extent that we make it easy to get into trouble we fail.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: right;"&gt;&lt;span style="color: #000000; font-family: book antiqua,palatino; font-size: medium;"&gt;&lt;em&gt;- by Rico Mariani&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In my &lt;a title="self-introduction" href="http://blogs.msdn.com/b/reiley/archive/2011/07/11/hello-world.aspx" target="_blank"&gt;self-introduction&lt;/a&gt;, I mentioned my past experience on developing ATL, CRT, MFC and STL. I've learned a lot from this experience, and as I work with people who develop services based on .NET platform, there are many interesting findings. Each time I stepped back and looked at things that have been developed, the more I&amp;nbsp;love the&amp;nbsp;"The Pit of Success" concept&amp;nbsp;brought up by&amp;nbsp;Rico Mariani. So here I'm trying to share some of my &lt;em&gt;personal&lt;/em&gt; understanding.&lt;/p&gt;
&lt;p&gt;ATL (not including ATL Server)&amp;nbsp;is my personal favorite library for the following reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ATL is a library instead of framework&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;in order to adopt ATL you don't have to change any existing architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ATL is lightweight&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;in most cases you can just use ATL header files, without dealing with *.lib files and DLLs&lt;/li&gt;
&lt;li&gt;ATL won't bloat the binary size too much&lt;/li&gt;
&lt;li&gt;ATL won't harm performance for sure&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ATL is predictable&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;debugging through ATL source is straightforward&lt;/li&gt;
&lt;li&gt;the main purpose of ATL is to make COM programming easier in C++, not to hide the complexity of the operating system concepts&lt;/li&gt;
&lt;li&gt;the COM wrapper has a very clear definition on the thread safety&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;CRT is the library from which I learned a lot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CRT acts as a bridge between the operating system and most applications&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;dealing with &lt;a title="application startup and cleanup" href="http://blogs.msdn.com/b/reiley/archive/2011/12/14/crt-startup.aspx" target="_blank"&gt;application startup and cleanup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;providing runtime services (e.g. backing C++ exception scope with SEH and exception filters)&lt;/li&gt;
&lt;li&gt;balancing between the underlying system implementation and the&amp;nbsp;C/C++ standard specification&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;CRT has evil contracts with C++ compiler toolchain&lt;/li&gt;
&lt;li&gt;CRT is not only consumed by normal applications, but also by operating system and compiler toolchain (which sounds like an infinite loop)&lt;/li&gt;
&lt;li&gt;CRT always sits in the frontline of supporting new hardware architecture&lt;/li&gt;
&lt;li&gt;CRT needs to be the most stable and compatible library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MFC is a framework consisting of class libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it's easy to get started with MFC&lt;/li&gt;
&lt;li&gt;MFC takes care of window management, messaging, COM and many great things&lt;/li&gt;
&lt;li&gt;you really need to understand MFC in order to use it well, especially when you run into bug hell&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;STL is a C++ template library, which I've used&amp;nbsp;extensively (in combination with &lt;a title="Boost" href="http://www.boost.org/" target="_blank"&gt;Boost&lt;/a&gt;) when I was in school, when I developed STL and when I have good reason to use STL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if I have a free choice, normally&amp;nbsp;I would tend not to use STL&lt;/li&gt;
&lt;li&gt;debugging template code is not easy, especially the code that makes extensive use of template meta-programming and &lt;a title="macro" href="http://blogs.msdn.com/b/reiley/archive/2011/08/12/macro-revisited.aspx" target="_blank"&gt;macro&lt;/a&gt;&amp;nbsp;meta-programming&lt;/li&gt;
&lt;li&gt;running code coverage analysis against template code is tricky (source line coverage is almost meaningless, you have to use basic block coverage)&lt;/li&gt;
&lt;li&gt;it's bad idea to pass (e.g. parameter, exception)&amp;nbsp;STL objects across module boundary, since&amp;nbsp;the underlying contract (e.g. object layout) might be different&lt;/li&gt;
&lt;li&gt;binary size might bloat and turn into a serious problem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10414490" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/CRT/">CRT</category></item><item><title>Error and Exception Revisited</title><link>http://blogs.msdn.com/b/reiley/archive/2013/04/05/error-and-exception-revisited.aspx</link><pubDate>Fri, 05 Apr 2013 14:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10407998</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10407998</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2013/04/05/error-and-exception-revisited.aspx#comments</comments><description>&lt;p&gt;&lt;span style="color: #000000; font-family: book antiqua,palatino; font-size: medium;"&gt;&lt;em&gt;Unless suffering is the direct and immediate object of life, our existence must entirely fail of its aim. It is absurd to look upon the enormous amount of pain that abounds everywhere in the world, and originates in needs and necessities inseparable from life itself, as serving no purpose at all and the result of mere chance. Each separate misfortune, as it comes, seems, no doubt, to be something exceptional; but misfortune in general is the rule.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: right;"&gt;&lt;span style="color: #000000; font-family: book antiqua,palatino; font-size: medium;"&gt;&lt;em&gt;- by Arthur Schopenhauer&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the world of programming, error and exceptions seem to be unavoidable, this is especially true when it comes to writing production quality code.&lt;/p&gt;
&lt;p&gt;Windows programming&amp;nbsp;can be&amp;nbsp;challenging when both error and exception are used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier; font-size: large;"&gt;Exception&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Exception always exists, even if you don't care,&amp;nbsp;it would disrupt the normal flow of execution. In Windows operating system exception is implemented as SEH/VEH, with the support from CPU.&lt;/p&gt;
&lt;p&gt;The key characteristics of exception in Windows are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disrupt the normal flow of execution, which translates to pipeline invalidation and slowness.&lt;/li&gt;
&lt;li&gt;Can be used consistently in&amp;nbsp;user mode and kernel mode.&lt;/li&gt;
&lt;li&gt;Always go to kernel mode, processed by CPU&amp;nbsp;exception or trap.&lt;/li&gt;
&lt;li&gt;Has a lot of great features like continue execution, first chance versus second chance.&lt;/li&gt;
&lt;li&gt;Unhandled exception would go to the operating system, which would kill the application (e.g. Dr. Watson)&amp;nbsp;or system (e.g. BSOD).&lt;/li&gt;
&lt;li&gt;If you swallow the exceptions used by the operating system or runtime (which you shouldn't catch), the application might not function correctly (e.g. you might get access violation while accessing the PAGE_GUARD page from callstack).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The third famous exception is Out of Memory - for device drivers and server application, you always want to handle it; for client application, probably not as critical (e.g. if Visual Studio IDE is running out of memory, we just let it crash).&lt;/p&gt;
&lt;p&gt;The second famous exception is Stack Overflow - for hosting environment and fundamental libraries like CRT, you need to take it into consideration; in&amp;nbsp;other cases it means you have design issue, and normally&amp;nbsp;you don't want to handle it.&lt;/p&gt;
&lt;p&gt;Let's take a look at the following pseudo code:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;try
{
  // do something
}
catch(StackOverflowException ex)
{
  log("oops, stack overflow {0}", ex.stack);
  throw ex;
}
finally
{
  // close file handle, etc.
}
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;There are several things I can tell:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Having "throw ex" would ruin the exception information, better use "throw" instead.&lt;/li&gt;
&lt;li&gt;The "log" function doesn't have much stack space, it could trigger another stack overflow.&lt;/li&gt;
&lt;li&gt;When the exception was re-thrown, we are already miles away from the&amp;nbsp;original place of the problem -&amp;nbsp;we are not keeping the scene intact, and nobody would want to debug a dump file for this case.&lt;/li&gt;
&lt;li&gt;The process is dying, close file handle will not make it any better,&amp;nbsp;operating system&amp;nbsp;would do that for you. More importantly, it is very likely that you are making things even worse.&lt;/li&gt;
&lt;li&gt;If you are using latest version of .NET framework, normally you are &lt;strong&gt;NOT&lt;/strong&gt;&amp;nbsp;allowed to catch StackOverflowException:
&lt;blockquote style="margin-right: 0px;" dir="ltr"&gt;
&lt;div style="background: #cccccc;"&gt;&lt;span style="font-family: verdana,geneva;"&gt;In prior versions of the .NET Framework, your application could catch a StackOverflowException object (for example, to recover from unbounded recursion). However, that practice is currently discouraged because significant additional code is required to reliably catch a stack overflow exception and continue program execution.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #bf100c;"&gt;Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default.&lt;/span&gt; Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface and Hosting Overview.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana,geneva;"&gt;Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition Platform Note: A thrown StackOverflowException cannot be caught by a try-catch block. Consequently, the exception causes the process to terminate immediately.&lt;/span&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The most famous exception is Access Violation, in normal cases this would be a killer bug which stop the entire development team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier; font-size: large;"&gt;Error&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Error is more like a convention, the main characteristics of error are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lightweight -&amp;nbsp;doesn't require infrastructure support from operating system and CPU.&lt;/li&gt;
&lt;li&gt;Less picky comparing to exception&amp;nbsp;-&amp;nbsp;error wouldn't complain whether you've paid enough attention to it, however it might eventually kill you if not handled properly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier;"&gt;Windows Error Code&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Most Win32 API would return BOOL value. If FALSE is returned, the error code is stored in TEB as DWORD, which can be retrieved by using GetLastError.&lt;/p&gt;
&lt;p&gt;You can use WinDBG's &lt;a title="!ext.gle" href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff563177.aspx" target="_blank"&gt;!ext.gle&lt;/a&gt; or Visual Studio's &lt;a title="$ERR" href="http://blogs.msdn.com/b/reiley/archive/2011/08/13/did-you-know.aspx" target="_blank"&gt;$ERR&lt;/a&gt; trick to retrieve the last error code from TEB, which also work for dump files.&lt;/p&gt;
&lt;p&gt;The good side of storing last error in a central place (e.g. TEB) is the ability to set &lt;a title="Data Breakpoint" href="http://blogs.msdn.com/b/reiley/archive/2011/07/21/data-breakpoint.aspx" target="_blank"&gt;Data Breakpoint&lt;/a&gt;&amp;nbsp;to see where is the&amp;nbsp;error coming from. Also in later version of Windows there is a feature to do similar things:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/6433.SetLastError.png"&gt;&lt;img style="border: 0px currentColor;" src="http://blogs.msdn.com/resized-image.ashx/__size/0x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/6433.SetLastError.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Registry API in advapi32.dll is special, Windows error code is returned directly as LONG (signed long).&lt;/p&gt;
&lt;p&gt;WinSock and NetAPI have similar concept but different mapping.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier;"&gt;NTSTATUS&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Lower layer of the operating system makes use of NTSTATUS, which has a similar structure as Win32 error, an incomplete mapping table can be found from &lt;a title="Mapping NT Status Error Codes to Win32 Error Codes" href="http://support.microsoft.com/kb/113996" target="_blank"&gt;Mapping NT Status Error Codes to Win32 Error Codes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For LSA (Local Security Authority)&amp;nbsp;specifically, the NTSTATUS return value can be converted to Win32 error using &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms721800.aspx" target="_blank"&gt;LsaNtStatusToWinError&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier;"&gt;HRESULT&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;COM makes use of HRESULT, which was designed to be a super container for all kinds of error codes. There is a macro HRESULT_FROM_WIN32 (p.s. in later version of Windows this has been &lt;a title="changed to an inline function" href="http://blogs.msdn.com/b/matthew_van_eerde/archive/2007/12/28/the-evolution-of-hresult-from-win32.aspx" target="_blank"&gt;changed to an inline function&lt;/a&gt;)&amp;nbsp;which converts Windows Error Code to HRESULT.&lt;/p&gt;
&lt;p&gt;One caveat about HRESULT is that one has to always keep in mind of S_OK, S_FALSE, SUCCEEDED and FAILED, and understand the differences.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Since there are so many different kinds of error codes, even people working in Microsoft may get confused, that's why people tend to create tools and make the situation better:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;WinDBG extension command &lt;a title="!ext.error" href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff562998.aspx" target="_blank"&gt;!ext.error&lt;/a&gt;, which supports both Windows Error Code and NTSTATUS.&lt;/li&gt;
&lt;li&gt;&lt;a title="Visual Studio debugger" href="http://msdn.microsoft.com/en-us/library/5tbh0w11.aspx" target="_blank"&gt;Visual Studio debugger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a title="Error Code Look-up" href="http://www.microsoft.com/en-us/download/details.aspx?id=985" target="_blank"&gt;Error Code Look-up&lt;/a&gt; tool, implemented by the Exchange team.&lt;/li&gt;
&lt;/ol&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10407998" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Pop+Quiz/">Pop Quiz</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Windows/">Windows</category></item><item><title>A Debugging Approach to Windows RT</title><link>http://blogs.msdn.com/b/reiley/archive/2012/12/26/a-debugging-approach-to-windows-rt.aspx</link><pubDate>Wed, 26 Dec 2012 13:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10380747</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10380747</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/12/26/a-debugging-approach-to-windows-rt.aspx#comments</comments><description>&lt;p&gt;Recently I got a &lt;a title="Surface with Windows RT" href="http://en.wikipedia.org/wiki/Microsoft_Surface" target="_blank"&gt;Surface with Windows&amp;nbsp;RT&lt;/a&gt;. Needless to mention, it's wonderful!&lt;/p&gt;
&lt;p&gt;I've figured out&amp;nbsp;some quick facts about Windows RT by looking at the &lt;span style="font-family: verdana,geneva;"&gt;C:\Windows\system32\ntdll.dll&lt;/span&gt; from Windows RT:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A&amp;nbsp;complete NT (instead of WINCE) kernel and almost a full stack of Windows operating system.&lt;/li&gt;
&lt;li&gt;Almost the same&amp;nbsp;&lt;a title="PE/COFF" href="http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx" target="_blank"&gt;PE/COFF&lt;/a&gt; structure as x86.&lt;/li&gt;
&lt;li&gt;Using ARM's "non classic RISC style" Thumb-2 instruction set (&lt;span style="font-family: verdana,geneva;"&gt;pImageNtHeaders-&amp;gt;FileHeader.Machine == &lt;strong&gt;IMAGE_FILE_MACHINE_ARMNT&lt;/strong&gt;&lt;/span&gt;), which has great code density, and in turn gives smaller binary and less memory pressure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've never had a chance to debug Thumb-2 code before, so I've listed the things I need to grasp:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fundamental ARM architecture and Thumb-2 instructions.&lt;/li&gt;
&lt;li&gt;ABI (Application Binary Interface), calling convention and&amp;nbsp;exception handling mechanism.&lt;/li&gt;
&lt;li&gt;Programming and debugging.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier; font-size: large;"&gt;Programming&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although Visual Studio 2012 doesn't&amp;nbsp;have an ARM version,&amp;nbsp;it&amp;nbsp;does included the x86 cross toolchain which allows targeting ARM architecture, which can be found from &lt;strong&gt;&lt;span style="font-family: verdana,geneva;"&gt;%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\bin\x86_arm\&lt;/span&gt;&lt;/strong&gt;. By setting the correct environment variable (INCLUDE, LIB, LIBPATH, PATH) we can generate ARM module smoothly.&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt;&amp;nbsp;main()
{
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;0;
}
&lt;/pre&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\&lt;span style="background-color: #00ff00;"&gt;x86_arm&lt;/span&gt;&amp;gt;&lt;strong&gt;cl.exe&amp;nbsp;/link /NODEFAULTLIB&amp;nbsp;/ENTRY:main test.cpp&lt;/strong&gt;
&lt;span style="color: #ff0000;"&gt;Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51106.1 for ARM &lt;/span&gt;Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 11.00.51106.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
/machine:arm
/NODEFAULTLIB
/ENTRY:main
test.obj
&lt;/pre&gt;
&lt;p&gt;By default Visual Studio doesn't allow generating native ARM binary, and the restriction was from a MSBuild property named &lt;strong&gt;WindowsSDKDesktopARMSupport&lt;/strong&gt;, by setting this property to true I could target ARM native without an issue.&lt;/p&gt;
&lt;p&gt;Another problem is that Windows SDK doesn't have the ARM version of import libraries, which means we don't have files like gdi32.lib and shell32.lib. The solution would be creating one either by writing a DEF file, or creating a stub module. Since we can get the&amp;nbsp;ARM version of DLLs&amp;nbsp;from Windows RT, it is easy to dump the export directory and create DEF file automatically, as long as the DLLs we use is not exporting mangled name (otherwise I would prefer to use stub module approach).&lt;/p&gt;
&lt;p&gt;This is what I got while running my very first hello.exe on Windows RT :)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/1307.HelloSurface.png"&gt;&lt;img style="border: 0px currentColor;" src="http://blogs.msdn.com/resized-image.ashx/__size/0x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/1307.HelloSurface.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For pure managed code programming, the .NET runtime in Surface RT&amp;nbsp;comes with the standard&amp;nbsp;C# compiler:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Hello&lt;/span&gt;
{
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt;&amp;nbsp;Main()
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;}
}
&lt;/pre&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;C:\Users\Reiley\Desktop&amp;gt;"&lt;strong&gt;%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe&lt;/strong&gt;" /noconfig /debug+ /platform:anycpu hello.cs
Microsoft (R) Visual &lt;span style="color: #ff0000;"&gt;C# Compiler version 4.0.30319.17929 &lt;/span&gt;
for Microsoft (R) &lt;span style="color: #ff0000;"&gt;.NET Framework 4.5&lt;/span&gt;
Copyright (C) Microsoft Corporation. All rights reserved.
&lt;/pre&gt;
&lt;p&gt;And this time I got something worse:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/1220.MsilSurface.png"&gt;&lt;img style="border: 0px currentColor;" src="http://blogs.msdn.com/resized-image.ashx/__size/0x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/1220.MsilSurface.png" alt="" width="700" height="135" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After changing the compiler flag&amp;nbsp;to target ARM instead of AnyCPU, it became better and I was again greeted with the "Windows cannot verify the digital signature ..." dialog.&lt;/p&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;C:\Users\Reiley\Desktop&amp;gt;"&lt;strong&gt;%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe&lt;/strong&gt;" /noconfig /debug+ /platform:&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;arm&lt;/strong&gt;&lt;/span&gt; hello.cs
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #000080; font-family: courier new,courier; font-size: large;"&gt;Debugging&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The x86 and amd64 version of WinDBG both support various architectures including ARM Thumb-2, which means you can open dump files from a PC. This is a good place to get started, and actually I copied notepad.exe from Surface to my PC and used&amp;nbsp;&lt;strong&gt;&lt;span style="font-family: verdana,geneva;"&gt;cdb.exe -z notepad.exe&lt;/span&gt;&lt;/strong&gt; to familiar myself with the ARM PE structure and disassembly.&lt;/p&gt;
&lt;p&gt;There is no&amp;nbsp;ARM version of WinDBG&amp;nbsp;available for public download. Also ntsd.exe is no longer shipped as part of the Windows since Vista.&lt;/p&gt;
&lt;p&gt;Visual Studio 2012 comes with a great debugger, together with a fantastic remote debugging agent. Jason Zander already explained how to setup remote debugging from his great&amp;nbsp;article "&lt;a title="What you need to know about developing for Windows on ARM" href="http://blogs.msdn.com/b/jasonz/archive/2012/06/12/what-you-need-to-know-about-developing-for-windows-on-arm-woa.aspx" target="_blank"&gt;What you need to know about developing for Windows on ARM&lt;/a&gt;". I'll just put a conclusion here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visual Studio 2012 doesn't have ARM version, in fact only x86 version is available.&lt;/li&gt;
&lt;li&gt;Visual Studio 2012 supports remote kernel debugging, however there is no direct way to enable kernel debugging on Windows RT device.&lt;/li&gt;
&lt;li&gt;Visual Studio 2012 comes with an ARM version of remote debugging agent, which makes it possible to do user mode debugging&amp;nbsp;on&amp;nbsp;nearly all processes. To unleash the power, run&amp;nbsp;remote debugging agent (msvsmon) as a service under an administrator account.&lt;/li&gt;
&lt;li&gt;User mode debugging on Windows RT is powerful enough that you can do whatever hack you like.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;(to be continued...)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10380747" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Windows/">Windows</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/ARM/">ARM</category></item><item><title>Postmortem Debugging - Better Late Than Never</title><link>http://blogs.msdn.com/b/reiley/archive/2012/10/21/postmortem-debugging-better-late-than-never.aspx</link><pubDate>Sun, 21 Oct 2012 15:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10361507</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10361507</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/10/21/postmortem-debugging-better-late-than-never.aspx#comments</comments><description>&lt;p&gt;If&amp;nbsp;there is a consistent repro, I&amp;nbsp;would definitely prefer&amp;nbsp;&lt;a title="Early Debugging" href="http://blogs.msdn.com/b/reiley/archive/2011/10/30/early-debugging.aspx" target="_blank"&gt;Early Debugging&lt;/a&gt;. However in the real life postmortem debugging seems to be unavoidable.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are three concepts I wish to clarify before digging into the details:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AeDebug&lt;/strong&gt; is a set of&amp;nbsp;registry keys which specify the behavior when unhandled exception happened in an user mode application.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: verdana,geneva;"&gt;\\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: verdana,geneva;"&gt;\\HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By&amp;nbsp;default AeDebug is configured to use drwtsn32.exe, which would capture a dump and terminate the application in problem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Just-In-Time Debugging&lt;/strong&gt;&amp;nbsp;(a.k.a. JIT Debugging) is a feature provided by most debuggers (e.g. CDB, NTSD, WinDBG and Visual Studio Debugger), which allows the debugger to be launched and attached to the application in problem.&lt;/p&gt;
&lt;p&gt;The JIT debugger shipped with Visual Studio&amp;nbsp;is called &lt;strong&gt;vsjitdebugger.exe&lt;/strong&gt;, which would pop up a window and let you decide&amp;nbsp;the next step. Visual Studio stepped further by allowing JIT debugging for scripts.&lt;/p&gt;
&lt;p&gt;Needless to mention, JIT Debugging is normally built on top of AeDebug.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Postmortem Debugging&lt;/strong&gt; is an overloaded term which could mean debugging a dump, or&amp;nbsp;JIT debugging.&lt;/p&gt;
&lt;p&gt;Since I will cover JIT debugging in another article, I would prefer referring dump file debugging as Postmortem Debugging.&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay, now let's go back to the topic, what would you do after receiving a dump file?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Understand the&amp;nbsp;source of the dump file - under which condition was the dump file generated. Once you've confirmed the dump is coming from a trusted source, try to find out when and where&amp;nbsp;the dump file was taken.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Consolas,courier new,courier;"&gt;0:001&amp;gt; &lt;strong&gt;.time&lt;/strong&gt;&lt;br /&gt; Debug session time: Mon Dec 3 17:36:58.997 2012 (UTC - 8:00)&lt;br /&gt; System Uptime: 2 days 23:31:41.638&lt;br /&gt; Process Uptime: 0 days 0:00:14.156&lt;br /&gt; Kernel time: 0 days 0:00:00.015&lt;br /&gt;User time: 0 days 0:00:00.000&lt;br /&gt; &lt;br /&gt; 0:001&amp;gt; &lt;strong&gt;vertarget&lt;/strong&gt;&lt;br /&gt; Windows 7 Version 7601 (Service Pack 1) MP (8 procs) Free x64 Product: LanManNt, suite: Enterprise TerminalServer SingleUserTS&lt;br /&gt; kernel32.dll version: 6.1.7601.17514 (win7sp1_rtm.101119-1850)&lt;br /&gt; Machine Name:&lt;br /&gt; Debug session time: Mon Dec 3 18:37:21.103 2012 (UTC - 8:00)&lt;br /&gt; System Uptime: 3 days 0:32:03.743&lt;br /&gt; Process Uptime: 0 days 1:00:36.261&lt;br /&gt; Kernel time: 0 days 0:00:00.015&lt;br /&gt; User time: 0 days 0:00:00.000&lt;br /&gt;&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;.lastevent&lt;/strong&gt;&lt;br /&gt;Last event: 14d0.1874: Break instruction exception - code 80000003 (first chance)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Check the dump file type&amp;nbsp;- mini dump or full dump, kernel dump or user mode dump, whether the dump contains an exception record. Normally WinDBG would&amp;nbsp;display the dump type when you open a dump file, here we'll use&amp;nbsp;the command learned in &lt;a title="Undocumented WinDBG" href="http://blogs.msdn.com/b/reiley/archive/2011/10/30/undocumented-windbg.aspx" target="_blank"&gt;Undocumented WinDBG&lt;/a&gt;.&lt;br /&gt;&amp;nbsp;&lt;span style="font-family: Consolas,courier new,courier;"&gt;&amp;nbsp;&lt;br /&gt; 0:001&amp;gt; &lt;strong&gt;.dumpdebug&lt;/strong&gt;&lt;br /&gt; ----- User Mini Dump Analysis&lt;br /&gt; MINIDUMP_HEADER:&lt;br /&gt;Version&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A793 (6804)&lt;br /&gt;NumberOfStreams 14&lt;br /&gt;Flags&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9164&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0004 MiniDumpWithHandleData&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0020 MiniDumpWithUnloadedModules&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0040 MiniDumpWithIndirectlyReferencedMemory&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0100 MiniDumpWithProcessThreadData&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1000 MiniDumpWithThreadInfo&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8000 MiniDumpWithFullAuxiliaryState&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If it's a user mode dump, additional information needs to be retrieved from the dump.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What is the command line, and whether the process is a generic host&amp;nbsp;such like dllhost.exe, svchost.exe taskhost.exe and w3wp.exe.&lt;/li&gt;
&lt;li&gt;Understand the bitness - whether it is a 64bit process or 32bit process.&amp;nbsp;It&amp;nbsp;would be tricky while debugging a 64bit dump of WOW32 process.&lt;/li&gt;
&lt;li&gt;Whether CLR is involved, and what is the CLR version (note there could be more than one CLR hosted).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(to be continued...)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10361507" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/debugger/">debugger</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Visual+Studio/">Visual Studio</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Windows/">Windows</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/AeDebug/">AeDebug</category></item><item><title>Windows 8 and conhost.exe</title><link>http://blogs.msdn.com/b/reiley/archive/2012/09/13/windows-8-and-conhost-exe.aspx</link><pubDate>Thu, 13 Sep 2012 14:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10349078</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10349078</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/09/13/windows-8-and-conhost-exe.aspx#comments</comments><description>&lt;p&gt;While debugging a console application on Windows 8, I noticed the console application is trying to create a process in the very beginning:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;windbg.exe -xe ld:ntdll.dll -c "bm ntdll!*CreateProcess*; g; k" cmd.exe&lt;/span&gt;&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;CommandLine: cmd.exe&lt;br /&gt;ModLoad: 000007ff`01d60000 000007ff`01f1e000&amp;nbsp;&amp;nbsp; ntdll.dll&lt;br /&gt;ntdll!RtlUserThreadStart:&lt;br /&gt;000007ff`01d7c3d0 4883ec48&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sub&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rsp,48h&lt;br /&gt;Processing initial command 'bm ntdll!*CreateProcess*; g; k'&lt;br /&gt;0:000&amp;gt; bm ntdll!*CreateProcess*; g; k&lt;br /&gt;&amp;nbsp; 1: 000007ff`01d90f60 @!"ntdll!RtlCreateProcessParametersEx"&lt;br /&gt;&amp;nbsp; 2: 000007ff`01d63070 @!"ntdll!NtCreateProcessEx"&lt;br /&gt;breakpoint 2 redefined&lt;br /&gt;&amp;nbsp; 2: 000007ff`01d63070 @!"ntdll!ZwCreateProcessEx"&lt;br /&gt;&amp;nbsp; 3: 000007ff`01e1bf74 @!"ntdll!RtlCreateProcessReflection"&lt;br /&gt;&amp;nbsp; 4: 000007ff`01da8bb4 @!"ntdll!RtlpCreateProcessRegistryInfo"&lt;br /&gt;&amp;nbsp; 5: 000007ff`01e1ceac @!"ntdll!RtlCreateProcessParameters"&lt;br /&gt;&amp;nbsp; 6: 000007ff`01d63651 @!"ntdll!ZwCreateProcess"&lt;br /&gt;breakpoint 6 redefined&lt;br /&gt;&amp;nbsp; 6: 000007ff`01d63651 @!"ntdll!NtCreateProcess"&lt;br /&gt;Breakpoint 1 hit&lt;br /&gt;Child-SP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call Site&lt;br /&gt;000000bf`8268e558 000007fe`feea02a4 ntdll!RtlCreateProcessParametersEx&lt;br /&gt;000000bf`8268e560 000007fe`feea00be KERNELBASE!ConsoleLaunchServerProcess+0x60&lt;br /&gt;000000bf`8268e5f0 000007fe`fee95d40 KERNELBASE!ConsoleAllocate+0xf6&lt;br /&gt;000000bf`8268e8c0 000007fe`fee7f6db KERNELBASE!ConsoleInitialize+0x1d1&lt;br /&gt;000000bf`8268e950 000007fe`fee7230d KERNELBASE!KernelBaseBaseDllInitialize+0x4dd&lt;br /&gt;000000bf`8268ec20 000007ff`01d6b9be KERNELBASE!KernelBaseDllInitialize+0xd&lt;br /&gt;000000bf`8268ec50 000007ff`01d8b3fc ntdll!LdrpCallInitRoutine+0x3e&lt;br /&gt;000000bf`8268eca0 000007ff`01d8a88b ntdll!LdrpInitializeNode+0x192&lt;br /&gt;000000bf`8268eda0 000007ff`01d8e74e ntdll!LdrpInitializeGraph+0x6f&lt;br /&gt;000000bf`8268ede0 000007ff`01d8c322 ntdll!LdrpInitializeGraph+0x8d&lt;br /&gt;000000bf`8268ee20 000007ff`01d8cc02 ntdll!LdrpPrepareModuleForExecution+0x1a5&lt;br /&gt;000000bf`8268ee70 000007ff`01d8337b ntdll!LdrpLoadDll+0x344&lt;br /&gt;000000bf`8268f0a0 000007ff`01d9264f ntdll!LdrLoadDll+0xa7&lt;br /&gt;000000bf`8268f120 000007ff`01d91826 ntdll!LdrpInitializeProcess+0x1664&lt;br /&gt;000000bf`8268f420 000007ff`01d7c1ae ntdll!_LdrpInitialize+0x1565e&lt;br /&gt;000000bf`8268f490 00000000`00000000 ntdll!LdrInitializeThunk+0xe&lt;/pre&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;dc rbx&lt;/strong&gt;&lt;br /&gt;000000bf`8268e660&amp;nbsp; 00000000 00000000 00000000 00000000&amp;nbsp; ................&lt;br /&gt;000000bf`8268e670&amp;nbsp; 003f005c 005c003f 003a0043 0057005c&amp;nbsp; &lt;span style="color: #0000ff;"&gt;\.?.?.\.C.:.\.W.&lt;/span&gt;&lt;br /&gt;000000bf`8268e680&amp;nbsp; 004e0049 004f0044 00530057 0073005c&amp;nbsp; &lt;span style="color: #0000ff;"&gt;I.N.D.O.W.S.\.s.&lt;/span&gt;&lt;br /&gt;000000bf`8268e690&amp;nbsp; 00730079 00650074 0033006d 005c0032&amp;nbsp; &lt;span style="color: #0000ff;"&gt;y.s.t.e.m.3.2.\.&lt;/span&gt;&lt;br /&gt;000000bf`8268e6a0&amp;nbsp; 006f0063 0068006e 0073006f 002e0074&amp;nbsp; &lt;span style="color: #0000ff;"&gt;c.o.n.h.o.s.t...&lt;/span&gt;&lt;br /&gt;000000bf`8268e6b0&amp;nbsp; 00780065 00200065 00780030 00660066&amp;nbsp; &lt;span style="color: #0000ff;"&gt;e.x.e. .0.x.&lt;/span&gt;f.f.&lt;br /&gt;000000bf`8268e6c0&amp;nbsp; 00660066 00660066 00660066 00000000&amp;nbsp; f.f.f.f.f.f.....&lt;br /&gt;000000bf`8268e6d0&amp;nbsp; 8268e960 000000bf 00000008 00000000&amp;nbsp; `.h.............&lt;/pre&gt;
&lt;p&gt;This means conhost.exe process&amp;nbsp;on Windows 8 will be created by the console application itself, instead of the CSRSS. And conhost.exe would always have the native bitness (on Windows 8 64bit version, only 64bit version of conhost.exe is available).&lt;/p&gt;
&lt;p&gt;Now&amp;nbsp;debug into conhost.exe using&lt;strong&gt; &lt;span style="font-family: verdana,geneva;"&gt;.childdbg&lt;/span&gt;&lt;/strong&gt;, it's pretty clear that conhost.exe is in charge of drawing the console window, handling user inputs and communicate with the console application:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;0&amp;nbsp; Id: 124c.d34 Suspend: 1 Teb: 000007f6`3311b000 Unfrozen&lt;br /&gt;Child-SP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call Site&lt;br /&gt;00000094`85aefb38 000007f6`33b91146 ntdll!NtWaitForSingleObject+0xa&lt;br /&gt;00000094`85aefb40 000007ff`00c9167e &lt;span style="color: #0000ff;"&gt;conhost!ConsoleIoThread&lt;/span&gt;+0xda&lt;br /&gt;00000094`85aefd80 000007ff`01d7c3f1 KERNEL32!BaseThreadInitThunk+0x1a&lt;br /&gt;00000094`85aefdb0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d&lt;/pre&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;#&amp;nbsp; 1&amp;nbsp; Id: 124c.1428 Suspend: 1 Teb: 000007f6`3311e000 Unfrozen&lt;br /&gt;Child-SP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call Site&lt;br /&gt;00000094`85b6fd28 000007ff`0140171e &lt;span style="color: #ff0000;"&gt;conhost!ConsoleWindowProc&lt;/span&gt;&lt;br /&gt;00000094`85b6fd30 000007ff`014014d7 USER32!UserCallWinProcCheckWow+0x13a&lt;br /&gt;00000094`85b6fdf0 000007f6`33b92fcc USER32!DispatchMessageWorker+0x1a7&lt;br /&gt;00000094`85b6fe70 000007ff`00c9167e &lt;span style="color: #0000ff;"&gt;conhost!ConsoleInputThread&lt;/span&gt;+0xd2&lt;br /&gt;00000094`85b6fed0 000007ff`01d7c3f1 KERNEL32!BaseThreadInitThunk+0x1a&lt;br /&gt;00000094`85b6ff00 00000000`00000000 ntdll!RtlUserThreadStart+0x1d&lt;/pre&gt;
&lt;p&gt;And cmd.exe itself doesn't draw the console window at all:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;0&amp;nbsp; Id: 1aec.5ec Suspend: 1 Teb: 000007f7`b280d000 Unfrozen&lt;br /&gt;Child-SP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call Site&lt;br /&gt;00000008`50fff5b8 000007fe`fee8f17c ntdll!NtDeviceIoControlFile+0xa&lt;br /&gt;00000008`50fff5c0 000007fe`fef0bb29 KERNELBASE!ConsoleCallServerGeneric+0x118&lt;br /&gt;00000008`50fff710 000007fe`fef0b986 KERNELBASE!ReadConsoleInternal+0x131&lt;br /&gt;00000008`50fff850 000007f7`b3621025 KERNELBASE!ReadConsoleW+0x1a&lt;br /&gt;00000008`50fff890 000007f7`b362bd3e cmd!ReadBufFromConsole+0x111&lt;br /&gt;00000008`50fff960 000007f7`b3604aae cmd!_chkstk+0x3820&lt;br /&gt;00000008`50fffae0 000007f7`b36042e4 &lt;span style="color: #0000ff;"&gt;cmd!Lex+0x4be&lt;/span&gt;&lt;br /&gt;00000008`50fffb50 000007f7`b362d560 &lt;span style="color: #0000ff;"&gt;cmd!Parser+0x128&lt;/span&gt;&lt;br /&gt;00000008`50fffba0 000007f7`b361b721 cmd!_chkstk+0x5032&lt;br /&gt;00000008`50fffc00 000007ff`00c9167e cmd!mystrchr+0x27d&lt;br /&gt;00000008`50fffc40 000007ff`01d7c3f1 KERNEL32!BaseThreadInitThunk+0x1a&lt;br /&gt;00000008`50fffc70 00000000`00000000 ntdll!RtlUserThreadStart+0x1d&lt;/pre&gt;
&lt;p&gt;The interesting thing is that if we use &lt;a title="Spy++" href="http://msdn.microsoft.com/en-us/library/dd460760" target="_blank"&gt;Spy++&lt;/a&gt;, it would report that the console window is associated with the &lt;a title="main thread" href="http://blogs.msdn.com/b/reiley/archive/2011/11/09/the-main-thread-problem.aspx" target="_blank"&gt;main thread&lt;/a&gt;&amp;nbsp;of cmd.exe process! I believe this is a hack in the underlying implementation of&amp;nbsp;&lt;strong&gt;&lt;span style="font-family: verdana,geneva;"&gt;GetWindowThreadProcessId&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;for backward compatibility. Also, Spy++ cannot be used to inspect conhost.exe message loop.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/0882.spyxx.png"&gt;&lt;img width="566" height="201" style="border: 0px currentColor;" src="http://blogs.msdn.com/resized-image.ashx/__size/0x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/0882.spyxx.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Due to the &lt;a title="side effects" href="http://blogs.msdn.com/b/reiley/archive/2011/08/28/side-effects-of-debugger.aspx" target="_blank"&gt;side effects&lt;/a&gt; of &lt;a title="IFEO" href="http://blogs.msdn.com/b/reiley/archive/2011/07/30/a-debugging-approach-to-ifeo.aspx" target="_blank"&gt;IFEO&lt;/a&gt; Debugger, console application would fail to start if IFEO Debugger is enabled for conhost.exe.&lt;/p&gt;
&lt;p&gt;The following call stack showed conhost.exe just created a normal window from Console Input Thread:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;USER32!&lt;span style="color: #0000ff;"&gt;CreateWindowExW&lt;/span&gt;&lt;br /&gt;conhost!CreateWindowsWindow+0x105&lt;br /&gt;conhost!InitWindowsSubsystem+0x69&lt;br /&gt;conhost!ConsoleInputThread+0x22&lt;br /&gt;KERNEL32!BaseThreadInitThunk+0x1a&lt;br /&gt;ntdll!RtlUserThreadStart+0x1d&lt;/pre&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;0:001&amp;gt; &lt;strong&gt;du @rdx&lt;/strong&gt;&lt;br /&gt;000007f6`33b9d460&amp;nbsp; "&lt;span style="color: #ff00ff;"&gt;ConsoleWindowClass&lt;/span&gt;"&lt;/pre&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;0:001&amp;gt; &lt;strong&gt;du @r8&lt;/strong&gt;&lt;br /&gt;00000025`f7dc37c0&amp;nbsp; "&lt;span style="color: #ff00ff;"&gt;C:\WINDOWS\SYSTEM32\cmd.exe&lt;/span&gt;"&lt;/pre&gt;
&lt;p&gt;When cmd.exe exits, the Console I/O&amp;nbsp;Thread would be notified:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;strong&gt;ntdll!NtTerminateProcess&lt;/strong&gt;+0xa&lt;br /&gt;&lt;strong&gt;ntdll!RtlExitUserProcess&lt;/strong&gt;+0xb6&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;conhost!ConsoleIoThread&lt;/span&gt;+0xac4&lt;br /&gt;KERNEL32!BaseThreadInitThunk+0x1a&lt;br /&gt;ntdll!RtlUserThreadStart+0x1d&lt;/pre&gt;
&lt;p&gt;(to be continued...)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10349078" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Windows/">Windows</category></item><item><title>Visualize Assembly using DGML</title><link>http://blogs.msdn.com/b/reiley/archive/2012/08/19/visualize-assembly-using-dgml.aspx</link><pubDate>Sun, 19 Aug 2012 15:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10341408</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10341408</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/08/19/visualize-assembly-using-dgml.aspx#comments</comments><description>&lt;p&gt;Starting from Visual Studio 2010 Ultimate there is a cool feature called DGML (&lt;a title="DGML" href="http://en.wikipedia.org/wiki/DGML" target="_blank"&gt;Directed Graph Markup Language&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I wrote a small script to convert the disassembled code from WinDBG into a DGML.&lt;/p&gt;
&lt;p&gt;In order to use it, simply type the following commands under a debug session:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;.shell&lt;span style="color: #000000;"&gt; -o &lt;strong&gt;LoadLibraryA&lt;/strong&gt;.dgml -ci "uf &lt;strong&gt;kernel32!LoadLibraryA&lt;/strong&gt;" cscript&lt;/span&gt;.exe /nologo dasm2dgml.js&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A&amp;nbsp;DGML file will be generated with the given name, and&amp;nbsp;here is what it looks like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/8154.DGML.png"&gt;&lt;img style="border: 0px currentColor;" src="http://blogs.msdn.com/resized-image.ashx/__size/0x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/8154.DGML.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/7446.DGML.png"&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-66/2451.DGML.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is the source code:&lt;/p&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;EBB&amp;nbsp;=&amp;nbsp;[];

&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;hypertext=&lt;span style="color: blue;"&gt;function&lt;/span&gt;(s){
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;r=[],L=s.length;
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;for&lt;/span&gt;(&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;i=0;i&amp;lt;L;i++){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;c=s.charAt(i);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;switch&lt;/span&gt;(c){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;&lt;span style="color: maroon;"&gt;'"'&lt;/span&gt;:r.push(&lt;span style="color: maroon;"&gt;'&amp;amp;quot;'&lt;/span&gt;);&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;amp;'&lt;/span&gt;:r.push(&lt;span style="color: maroon;"&gt;'&amp;amp;amp;'&lt;/span&gt;);&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;lt;'&lt;/span&gt;:r.push(&lt;span style="color: maroon;"&gt;'&amp;amp;lt;'&lt;/span&gt;);&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;gt;'&lt;/span&gt;:r.push(&lt;span style="color: maroon;"&gt;'&amp;amp;gt;'&lt;/span&gt;);&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;default&lt;/span&gt;:r.push(c);}}
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;r.join(&lt;span style="color: maroon;"&gt;''&lt;/span&gt;);
};

&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;map=&lt;span style="color: blue;"&gt;function&lt;/span&gt;(f,v){&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;L=v.length,r=[];&lt;span style="color: blue;"&gt;for&lt;/span&gt;(&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;i=0;i&amp;lt;L;i++)r.push(f(v[i]));&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;r;};

(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(){
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;blk;

&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;CExtendedBasicBlock&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;function&lt;/span&gt;(name,&amp;nbsp;previous,&amp;nbsp;next){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Address&amp;nbsp;=&amp;nbsp;&lt;span style="color: maroon;"&gt;''&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Code&amp;nbsp;=&amp;nbsp;[];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Name&amp;nbsp;=&amp;nbsp;name;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Previous&amp;nbsp;=&amp;nbsp;previous;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Next&amp;nbsp;=&amp;nbsp;next;
&amp;nbsp;&amp;nbsp;};

&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;while&lt;/span&gt;(&lt;span style="color: blue;"&gt;true&lt;/span&gt;)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;(WScript.StdIn.AtEndOfStream)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;strSourceLine&amp;nbsp;=&amp;nbsp;WScript.StdIn.ReadLine().replace(/(^\s+)|(\s+$)/g,&amp;nbsp;&lt;span style="color: maroon;"&gt;''&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;(!strSourceLine)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;continue&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;(strSourceLine.match(/.*:$/))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;blk&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;CExtendedBasicBlock(strSourceLine.slice(0,&amp;nbsp;-1));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EBB.push(blk);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;else&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;blk.Address&amp;nbsp;=&amp;nbsp;blk.Address&amp;nbsp;||&amp;nbsp;strSourceLine.match(/^[^\s]+/)[0];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;blk.Code.push(strSourceLine.replace(/[^\s]*\s+/,&amp;nbsp;&lt;span style="color: maroon;"&gt;''&lt;/span&gt;).replace(/[^\s]*\s+/,&amp;nbsp;&lt;span style="color: maroon;"&gt;''&lt;/span&gt;));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;}
})();

EBB&amp;nbsp;=&amp;nbsp;EBB.sort(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(x,&amp;nbsp;y){&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;x.Address&amp;nbsp;==&amp;nbsp;y.Address&amp;nbsp;?&amp;nbsp;0&amp;nbsp;:&amp;nbsp;x.Address&amp;nbsp;&amp;gt;&amp;nbsp;y.Address&amp;nbsp;?&amp;nbsp;1&amp;nbsp;:&amp;nbsp;-1;&amp;nbsp;});
&lt;span style="color: blue;"&gt;for&lt;/span&gt;(&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;1;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;EBB.length;&amp;nbsp;i++)
{
&amp;nbsp;&amp;nbsp;EBB[i].Previous&amp;nbsp;=&amp;nbsp;EBB[i&amp;nbsp;-&amp;nbsp;1];
&amp;nbsp;&amp;nbsp;EBB[i].Previous.Next&amp;nbsp;=&amp;nbsp;EBB[i];
}

WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;lt;DirectedGraph&amp;nbsp;Background="#FFFFFF"&amp;nbsp;GraphDirection="TopToBottom"&amp;nbsp;xmlns="http://schemas.microsoft.com/vs/2009/dgml"&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;Nodes&amp;gt;'&lt;/span&gt;);
map(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(blk){
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;content&amp;nbsp;=&amp;nbsp;hypertext(blk.Name&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;nbsp;('&lt;/span&gt;&amp;nbsp;+&amp;nbsp;blk.Address&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;')'&lt;/span&gt;)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;amp;#xD;&amp;amp;#xA;'&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;map(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(instruction){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content&amp;nbsp;+=&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;amp;#xD;&amp;amp;#xA;'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(instruction);
&amp;nbsp;&amp;nbsp;},&amp;nbsp;blk.Code);
&amp;nbsp;&amp;nbsp;WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Node&amp;nbsp;Id="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(blk.Name)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;Label="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;content&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
},&amp;nbsp;EBB);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;/Nodes&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;Links&amp;gt;'&lt;/span&gt;);
map(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(blk){
&amp;nbsp;&amp;nbsp;map(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(instruction){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;map(&lt;span style="color: blue;"&gt;function&lt;/span&gt;(x){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;instruction.indexOf(x.Name);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;idx&amp;nbsp;&amp;gt;=&amp;nbsp;0&amp;nbsp;?&amp;nbsp;instruction.charAt(idx&amp;nbsp;+&amp;nbsp;x.Name.length)&amp;nbsp;:&amp;nbsp;-1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;(idx&amp;nbsp;==&amp;nbsp;&lt;span style="color: maroon;"&gt;''&lt;/span&gt;&amp;nbsp;||&amp;nbsp;idx&amp;nbsp;==&amp;nbsp;&lt;span style="color: maroon;"&gt;'&amp;nbsp;'&lt;/span&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Link&amp;nbsp;Source="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(blk.Name)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;Target="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(x.Name)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&amp;nbsp;EBB);
&amp;nbsp;&amp;nbsp;},&amp;nbsp;blk.Code);
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;(blk.Next&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!(blk.Code[blk.Code.length&amp;nbsp;-&amp;nbsp;1].match(/^[^\s]+/)[0]&amp;nbsp;&lt;span style="color: blue;"&gt;in&lt;/span&gt;&amp;nbsp;{jmp:&amp;nbsp;0,&amp;nbsp;ret:&amp;nbsp;0}))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Link&amp;nbsp;Category="FallThrough"&amp;nbsp;Source="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(blk.Name)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;Target="'&lt;/span&gt;&amp;nbsp;+&amp;nbsp;hypertext(blk.Next.Name)&amp;nbsp;+&amp;nbsp;&lt;span style="color: maroon;"&gt;'"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
},&amp;nbsp;EBB);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;/Links&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;Styles&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Style&amp;nbsp;TargetType="Node"&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="FontFamily"&amp;nbsp;Value="Consolas"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="FontSize"&amp;nbsp;Value="11"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="Background"&amp;nbsp;Value="White"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="NodeRadius"&amp;nbsp;Value="2"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Style&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Style&amp;nbsp;TargetType="Link"&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Condition&amp;nbsp;Expression="HasCategory(\'FallThrough\')"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="Background"&amp;nbsp;Value="Red"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Setter&amp;nbsp;Property="Stroke"&amp;nbsp;Value="Red"&amp;nbsp;/&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Style&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;nbsp;&amp;nbsp;&amp;lt;/Styles&amp;gt;'&lt;/span&gt;);
WScript.Echo(&lt;span style="color: maroon;"&gt;'&amp;lt;/DirectedGraph&amp;gt;'&lt;/span&gt;);
&lt;/pre&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This script cannot generate 100% accurate control flow diagram, you will have to do further analysis (e.g. &lt;strong&gt;jmp eax&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;I haven't got a chance to test under WOA (ARM32), so I leave it as a homework for our readers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Enjoy:)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10341408" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/Pop+Quiz/">Pop Quiz</category></item><item><title>Using Function Evaluation in WinDBG</title><link>http://blogs.msdn.com/b/reiley/archive/2012/08/19/using-function-evaluation-in-windbg.aspx</link><pubDate>Sat, 18 Aug 2012 16:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10341271</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10341271</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/08/19/using-function-evaluation-in-windbg.aspx#comments</comments><description>&lt;p&gt;People who develop debuggers would know in theory you cannot have a perfect disassembler (especially for x86)&amp;nbsp;and stepper (especially for&amp;nbsp;Step Over). People who&amp;nbsp;develop commercial&amp;nbsp;debuggers would know Function Evaluation (a.k.a. funceval)&amp;nbsp;is a big challenge while implementing an&amp;nbsp;Expression Evaluator. And people who develop the Visual Studio Debugger would face other difficulties - Interop Debugging, Edit &amp;amp; Continue.&lt;/p&gt;
&lt;p&gt;In this article, I'm not going to explain the&amp;nbsp;bloody details of funceval, I just demonstrate how to use funceval in WinDBG and how powerful it is.&lt;/p&gt;
&lt;p&gt;Previously we mentioned the &lt;strong&gt;&lt;span style="font-family: verdana,geneva;"&gt;.call&lt;/span&gt;&lt;/strong&gt; command in &lt;a href="http://blogs.msdn.com/b/reiley/archive/2011/08/07/microsoft-binary-technologies.aspx" target="_blank"&gt;Microsoft Binary Technologies&lt;/a&gt;, at that&amp;nbsp;time we were not able to invoke the function since we don't have private symbols - funceval requires private symbol since debugger needs to understand the calling convention, which is stripped out in public symbol.&lt;/p&gt;
&lt;p&gt;While I cannot use private symbols writting articles for this blog (private symbol is Microsoft privacy, also debugging without private symbol is much more fun), the way I'd take is to create a proxy DLL:&lt;/p&gt;
&lt;hr style="width: 100%;" width="100%" /&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;&amp;lt;Windows.h&amp;gt;&lt;/span&gt;

VOID&amp;nbsp;WINAPI&amp;nbsp;SetLastError(DWORD&amp;nbsp;dwErrCode){}
&lt;/pre&gt;
&lt;hr style="width: 100%;" width="100%" /&gt;
&lt;p&gt;Now compile the code into a DLL, with PDB file generated:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;cl.exe funceval.cpp /D UNICODE /Fd /GS- /LD /Od /Zi /link /NOENTRY /NODEFAULTLIB /RELEASE /SUBSYSTEM:CONSOLE&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In order to use the proxy DLL, we will use the following approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Launch a debug session.&lt;/li&gt;
&lt;li&gt;Allocate memory from debugee process.&lt;/li&gt;
&lt;li&gt;Inject the proxy DLL into the allocated memory (note that we skipped PE relocation).&lt;/li&gt;
&lt;li&gt;Load private symbol of the proxy DLL.&lt;/li&gt;
&lt;li&gt;Use WinDBG &lt;strong&gt;&lt;span style="font-family: verdana,geneva;"&gt;.call&lt;/span&gt;&lt;/strong&gt; command to kick off funceval from proxy DLL.&lt;/li&gt;
&lt;li&gt;Change the IP register to the real address we want to execute.&lt;/li&gt;
&lt;li&gt;Start evaluating.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the automation script, enjoy!&lt;/p&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;$$ cdb.exe -xe cpr -c "$$&amp;gt;a&amp;lt; .\funceval.txt" notepad.exe

.echo [Launch Script]

$$ &lt;span style="color: #0000ff;"&gt;change the following value to the size of funceval.dll&lt;/span&gt;
r $t1 = &lt;span style="color: #ff0000;"&gt;&lt;b&gt;0n1536&lt;/b&gt;&lt;/span&gt;

bp @$exentry; g

.echo [Allocate Memory]
.foreach ( token { .dvalloc @$t1 } ) {
	aS alias token
	.block {
		.if ($spat("${alias}", "[0-9a-f]+")) {
			r $t2 = 0x${alias}
		}
	}
	ad /q alias
}

.printf "[Load Helper DLL(base address = %p, size = %p)]\n", @$t2, @$t1
.readmem funceval.dll @$t2 (@$t1+@$t2-1)

.block {
	.sympath .
}

$$.symopt+ 0x40

.reload /s /f funceval.dll=$t2

$$.symopt- 0x40

.echo [Function Evaluation]
.call /s funceval!SetLastError kernel32!SetLastError(7777)

g

!gle

.dvfree @$t2 0
&lt;/pre&gt;
&lt;p&gt;And here is the output from my machine:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;[Allocate Memory]
[Load Helper DLL(base address = 00020000, size = 00000600)]
Reading 600 bytes.
[Function Evaluation]
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
LastErrorValue: (Win32) 0x1e61 (&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;7777&lt;/strong&gt;&lt;/span&gt;) - &amp;lt;Unable to get error code text&amp;gt;
LastStatusValue: (NTSTATUS) 0 - STATUS_WAIT_0
Freed 0 bytes starting at 00020000&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10341271" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/debugger/">debugger</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/funceval/">funceval</category></item><item><title>A Debugging Approach to Application Verifier</title><link>http://blogs.msdn.com/b/reiley/archive/2012/08/17/a-debugging-approach-to-application-verifier.aspx</link><pubDate>Fri, 17 Aug 2012 15:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10340995</guid><dc:creator>Reiley Yang</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/reiley/rsscomments.aspx?WeblogPostID=10340995</wfw:commentRss><comments>http://blogs.msdn.com/b/reiley/archive/2012/08/17/a-debugging-approach-to-application-verifier.aspx#comments</comments><description>&lt;p&gt;&lt;a title="Application Verifier" href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff538115.aspx" target="_blank"&gt;Application Verifier&lt;/a&gt;,&amp;nbsp;also known&amp;nbsp;as AppVerifier,&amp;nbsp;is a dynamic instrumentation tool for user mode applications. It is free available from SDK/PSDK, with a set of GUI applications and DLL extensions, plus a good document.&lt;/p&gt;
&lt;p&gt;Let's begin by adding the most famous application - notepad.exe - from the appverif.exe GUI, and&amp;nbsp;launch&amp;nbsp;notepad.exe from &lt;a title="WinDBG" href="http://blogs.msdn.com/b/reiley/archive/2011/07/21/visual-studio-debugger-or-windbg.aspx" target="_blank"&gt;WinDBG&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;windbg.exe notepad.exe&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: consolas,courier new,courier; font-size: small;"&gt;ModLoad: 00620000 00650000&amp;nbsp;&amp;nbsp; notepad.exe&lt;br /&gt;ModLoad: 77c00000 77d80000&amp;nbsp;&amp;nbsp; ntdll.dll&lt;br /&gt;Page heap: pid 0xE10: page heap enabled with flags 0x3.&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;AVRF: notepad.exe: pid 0xE10: flags 0x80643027: application verifier enabled&lt;/span&gt;&lt;br /&gt;ModLoad: 10350000 103b0000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\&lt;span style="color: #ff00ff;"&gt;verifier.dll&lt;/span&gt;&lt;br /&gt;Page heap: pid 0xE10: page heap enabled with flags 0x3.&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;AVRF: notepad.exe: pid 0xE10: flags 0x80643027: application verifier enabled&lt;/span&gt;&lt;br /&gt;ModLoad: 5cca0000 5cccb000&amp;nbsp;&amp;nbsp; C:\Windows\SysWOW64\&lt;span style="color: #ff00ff;"&gt;vrfcore.dll&lt;/span&gt;&lt;br /&gt;ModLoad: 0f820000 0f878000&amp;nbsp;&amp;nbsp; C:\Windows\SysWOW64\&lt;span style="color: #ff00ff;"&gt;vfbasics.dll&lt;/span&gt;&lt;br /&gt;ModLoad: 75330000 75440000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\kernel32.dll&lt;br /&gt;ModLoad: 75c40000 75c86000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\KERNELBASE.dll&lt;br /&gt;ModLoad: 76ee0000 76f80000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\ADVAPI32.dll&lt;br /&gt;ModLoad: 75fd0000 7607c000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\msvcrt.dll&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Like we've mentioned in &lt;a title="A Debugging Approach to IFEO" href="http://blogs.msdn.com/b/reiley/archive/2011/07/30/a-debugging-approach-to-ifeo.aspx" target="_blank"&gt;A Debugging Approach to IFEO&lt;/a&gt;, the loader code in NTDLL knows how to initialize application verifier.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;windbg.exe -xe cpr notepad.exe&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: consolas,courier new,courier; font-size: small;"&gt;0:000&amp;gt; &lt;strong&gt;sxeld verifier&lt;/strong&gt;&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;g&lt;/strong&gt;&lt;br /&gt;Page heap: pid 0x1DBC: page heap enabled with flags 0x3.&lt;br /&gt;AVRF: notepad.exe: pid 0x1DBC: flags 0x80643027: application verifier enabled&lt;br /&gt;ModLoad: 105f0000 10650000&amp;nbsp;&amp;nbsp; C:\Windows\syswow64\verifier.dll&lt;br /&gt;eax=00000000 ebx=77d07e00 ecx=00000000 edx=00000000 esi=7efdd000 edi=00000000&lt;br /&gt;eip=77c1fc42 esp=0018f3a8 ebp=0018f790 iopl=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nv up ei pl zr na pe nc&lt;br /&gt;cs=0023&amp;nbsp; ss=002b&amp;nbsp; ds=002b&amp;nbsp; es=002b&amp;nbsp; fs=0053&amp;nbsp; gs=002b&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; efl=00000246&lt;br /&gt;ntdll!ZwMapViewOfSection+0x12:&lt;br /&gt;77c1fc42 83c404&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esp,4&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;k&lt;/strong&gt;&lt;br /&gt;ChildEBP RetAddr&lt;br /&gt;0018f3a8 77ca6fa3 ntdll!ZwMapViewOfSection+0x12&lt;br /&gt;0018f790 77ca7c29 ntdll!AvrfMiniLoadDll+0x3d1&lt;br /&gt;0018f7c4 77ca1075 ntdll!AVrfInitializeVerifier+0x252&lt;br /&gt;0018f7fc 77c80759 ntdll!LdrpInitializeApplicationVerifierPackage+0xab&lt;br /&gt;0018f878 77c45383 &lt;span style="color: #ff0000;"&gt;ntdll!LdrpInitializeExecutionOptions&lt;/span&gt;+0x222&lt;br /&gt;0018fa08 77c452d6 ntdll!LdrpInitializeProcess+0x261&lt;br /&gt;0018fa58 77c39e79 ntdll!_LdrpInitialize+0x78&lt;br /&gt;0018fa68 00000000 ntdll!LdrInitializeThunk+0x10&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;By reading the disassembled code, it's obvious that ntdll!RtlOpenImageFileOptionsKey is used to retrieve the IFEO related information. NTDLL would read from IFEO to see if the application is registered, and&amp;nbsp;whether application verifier is enabled in &lt;strong&gt;GlobalFlag&lt;/strong&gt; (GFLAG). If GFLAG &amp;amp; 0x100 is non-zero, NTDLL would load &lt;strong&gt;verifier.dll&lt;/strong&gt; from %windir%\system32 or %windir%\syswow64, depending on the target bitness.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: consolas,courier new,courier; font-size: small;"&gt;0:000&amp;gt; &lt;strong&gt;sxeld&lt;/strong&gt;&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;g&lt;/strong&gt;&lt;br /&gt;Page heap: pid 0x1DBC: page heap enabled with flags 0x3.&lt;br /&gt;AVRF: notepad.exe: pid 0x1DBC: flags 0x80643027: application verifier enabled&lt;br /&gt;ModLoad: &lt;span style="color: #ff00ff;"&gt;0f6f0000&lt;/span&gt; 0f71b000&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;C:\Windows\SysWOW64\vrfcore.dll&lt;/span&gt;&lt;br /&gt;eax=00000000 ebx=00000000 ecx=0018f600 edx=0018f601 esi=7efdd000 edi=0018f628&lt;br /&gt;eip=77c1fc42 esp=0018f4fc ebp=0018f550 iopl=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nv up ei pl zr na pe nc&lt;br /&gt;cs=0023&amp;nbsp; ss=002b&amp;nbsp; ds=002b&amp;nbsp; es=002b&amp;nbsp; fs=0053&amp;nbsp; gs=002b&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; efl=00000246&lt;br /&gt;ntdll!ZwMapViewOfSection+0x12:&lt;br /&gt;77c1fc42 83c404&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esp,4&lt;br /&gt;0:000&amp;gt; &lt;strong&gt;k&lt;/strong&gt;&lt;br /&gt;ChildEBP RetAddr&lt;br /&gt;0018f4fc 77c3beec ntdll!ZwMapViewOfSection+0x12&lt;br /&gt;0018f550 77c3c578 ntdll!LdrpMapViewOfSection+0xc7&lt;br /&gt;0018f644 77c3c3a9 ntdll!LdrpFindOrMapDll+0x333&lt;br /&gt;0018f7c4 77c3c4d5 ntdll!LdrpLoadDll+0x2b2&lt;br /&gt;0018f7fc 77ca746f ntdll!LdrLoadDll+0xaa&lt;br /&gt;0018f850 77ca7aaa &lt;span style="color: #ff0000;"&gt;ntdll!AVrfpLoadAndInitializeProvider&lt;/span&gt;+0x6f&lt;br /&gt;0018f874 77c8117c ntdll!AVrfInitializeVerifier+0xd3&lt;br /&gt;0018fa08 77c452d6 ntdll!LdrpInitializeProcess+0xfba&lt;br /&gt;0018fa58 77c39e79 ntdll!_LdrpInitialize+0x78&lt;br /&gt;0018fa68 00000000 ntdll!LdrInitializeThunk+0x10&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;NTDLL&amp;nbsp;would further check if&amp;nbsp;IFEO has a REG_SZ value named &lt;strong&gt;VerifierDlls&lt;/strong&gt;. If&amp;nbsp;VerifierDlls is found, it's value will be splitted into DLL names, and these DLLs would be loaded into the target process one by one.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: consolas,courier new,courier; font-size: small;"&gt;0:000&amp;gt; &lt;strong&gt;dt ntdll!IMAGE_DOS_HEADER &lt;span style="color: #ff00ff;"&gt;0f6f0000&lt;/span&gt;&lt;/strong&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x000 e_magic&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0x5a4d&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x002 e_cblp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0x90&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x004 e_cp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 3&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x006 e_crlc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x008 e_cparhdr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 4&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x00a e_minalloc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x00c e_maxalloc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0xffff&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x00e e_ss&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x010 e_sp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0xb8&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x012 e_csum&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x014 e_ip&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x016 e_cs&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x018 e_lfarlc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0x40&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x01a e_ovno&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x01c e_res&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : [4] 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x024 e_oemid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x026 e_oeminfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x028 e_res2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : [10] 0&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x03c e_lfanew&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;span style="color: #ff00ff;"&gt;0n240&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: consolas,courier new,courier; font-size: small;"&gt;0:000&amp;gt; &lt;strong&gt;dt ntdll!_IMAGE_NT_HEADERS OptionalHeader.AddressOfEntryPoint &lt;span style="color: #ff00ff;"&gt;0f6f0000&lt;/span&gt;+&lt;span style="color: #ff00ff;"&gt;0n240&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; +0x018 OptionalHeader&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +0x010 AddressOfEntryPoint&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;strong&gt;&lt;span style="color: #ff00ff;"&gt;0x2c86&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #000000; font-family: consolas,courier new,courier; font-size: small;"&gt;0:000&amp;gt; &lt;strong&gt;ln &lt;span style="color: #ff00ff;"&gt;0f6f0000&lt;/span&gt;+&lt;span style="color: #ff00ff;"&gt;0x2c86&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;(0f6f2c86)&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;vrfcore!DllMain&lt;/span&gt;&amp;nbsp;&amp;nbsp; |&amp;nbsp; (0f642ca7)&amp;nbsp;&amp;nbsp; vrfcore!VerifierOpenLayerProperties&lt;br /&gt;Exact matches:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!DllMain = &amp;lt;no type information&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The above steps can be automated using script:&lt;/p&gt;
&lt;pre style="background: #ffffe0; color: black; font-family: Consolas;"&gt;$$ cdb.exe -xe cpr -c "$$&amp;gt;a&amp;lt; .\appverif.txt" notepad.exe

.echo [Launch Script]

sxeld vrfcore; g; sxdld

$$ get vrfcore.dll base address
r $t1 = vrfcore

.if @$ptrsize == 8 {
	aS IMAGE_NT_HEADERS _IMAGE_NT_HEADERS64
} .else {
	aS IMAGE_NT_HEADERS _IMAGE_NT_HEADERS
}

$$ get OEP offset
.block {
	r $t2 = @@c++(((ntdll!${IMAGE_NT_HEADERS}*)(@$t1 + ((ntdll!_IMAGE_DOS_HEADER*)@$t1)-&amp;gt;e_lfanew))-&amp;gt;OptionalHeader.AddressOfEntryPoint)
}

$$ break at OEP
bp @$t1 + @$t2; g; bc 0

.echo [Hit OEP]
k

.echo [Arguments]
dd esp L4
&lt;/pre&gt;
&lt;p&gt;Now we've successfully located the&amp;nbsp;OEP (Original Entry Point, we mentioned that in &lt;a title="Data Breakpoints" href="http://blogs.msdn.com/b/reiley/archive/2011/07/21/data-breakpoint.aspx" target="_blank"&gt;Data Breakpoints&lt;/a&gt;) for vrfcore.dll, set a breakpoint.&lt;/p&gt;
&lt;p&gt;When we hit the breakpoint on &lt;span style="font-family: verdana,geneva;"&gt;vrfcore!DllMain&lt;/span&gt;, take a look at the top frame and it showed the second argument passed in is 4:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: verdana,geneva;"&gt;DllMain(HINSTANCE hinstDLL = &lt;span style="color: #ff00ff;"&gt;0f6f0000&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;DWORD fdwReason= 4&lt;/span&gt;, LPVOID lpvReserved)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It looks like fdwReason = 4 is undocumented on MSDN:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DLL_PROCESS_DETACH = 0&lt;/li&gt;
&lt;li&gt;DLL_PROCESS_ATTACH = 1&lt;/li&gt;
&lt;li&gt;DLL_THREAD_ATTACH = 2&lt;/li&gt;
&lt;li&gt;DLL_THREAD_DETACH = 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By looking at the disassembled code, the following instructions looks suspecious:&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #000000; font-family: consolas,courier new,courier; font-size: small;"&gt;vsvrfcore!_DllMain:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edi, edi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; push&amp;nbsp;&amp;nbsp;&amp;nbsp; ebp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ebp, esp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, dword ptr [ebp+0Ch]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; push&amp;nbsp;&amp;nbsp;&amp;nbsp; ebx&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; push&amp;nbsp;&amp;nbsp;&amp;nbsp; esi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esi, esi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; push&amp;nbsp;&amp;nbsp;&amp;nbsp; edi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edi, edi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; inc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sub&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, edi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; je&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x426&lt;br /&gt; &lt;br /&gt; vrfcore!_DllMain+0x18:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dec&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; je&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x2aa&lt;br /&gt; &lt;br /&gt; vrfcore!_DllMain+0x1f:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dec&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; je&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x29b&lt;br /&gt; &lt;br /&gt; vrfcore!_DllMain+0x26:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dec&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; je&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x28c&lt;br /&gt; &lt;br /&gt; vrfcore!_DllMain+0x2d:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dec&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; jne&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x283&lt;br /&gt;&lt;br /&gt; vrfcore!_DllMain+0x34:&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ebx, dword ptr [ebp+10h]&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ebx, edi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; jne&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!_DllMain+0x79&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #000000; font-family: consolas,courier new,courier; font-size: small;"&gt;vrfcore!_DllMain+0x131:&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edi, offset vrfcore!VfCoreProvider&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dword ptr [ebx], edi&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call&amp;nbsp;&amp;nbsp;&amp;nbsp; vrfcore!VfCoreProviderInitialize&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From the highlighted code we can see when fdwReason is 4, the following assignment would happen:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: verdana,geneva;"&gt;*lpvReserved = (LPVOID)(&amp;amp;vrfcore!VfCoreProvider)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;By looking into the Win2003R2 DDK headers, we can find out the layout defintion for Verifier Provider Descript. So it's time to write a small provider now.&lt;/p&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;&lt;span style="color: blue;"&gt;#define&lt;/span&gt;&amp;nbsp;WIN32_LEAN_AND_MEAN
&lt;span style="color: blue;"&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;&amp;lt;Windows.h&amp;gt;&lt;/span&gt;

&lt;span style="color: green;"&gt;//&amp;nbsp;Borrowed&amp;nbsp;from&amp;nbsp;Win2003R2&amp;nbsp;DDK&lt;/span&gt;

&lt;span style="color: blue;"&gt;#define&lt;/span&gt;&amp;nbsp;DLL_PROCESS_VERIFIER&amp;nbsp;4

&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;VOID&amp;nbsp;(NTAPI&amp;nbsp;*&amp;nbsp;RTL_VERIFIER_DLL_LOAD_CALLBACK)&amp;nbsp;(PWSTR&amp;nbsp;DllName,&amp;nbsp;PVOID&amp;nbsp;DllBase,&amp;nbsp;SIZE_T&amp;nbsp;DllSize,&amp;nbsp;PVOID&amp;nbsp;Reserved);
&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;VOID&amp;nbsp;(NTAPI&amp;nbsp;*&amp;nbsp;RTL_VERIFIER_DLL_UNLOAD_CALLBACK)&amp;nbsp;(PWSTR&amp;nbsp;DllName,&amp;nbsp;PVOID&amp;nbsp;DllBase,&amp;nbsp;SIZE_T&amp;nbsp;DllSize,&amp;nbsp;PVOID&amp;nbsp;Reserved);
&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;VOID&amp;nbsp;(NTAPI&amp;nbsp;*&amp;nbsp;RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK)&amp;nbsp;(PVOID&amp;nbsp;AllocationBase,&amp;nbsp;SIZE_T&amp;nbsp;AllocationSize);

&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;struct&lt;/span&gt;&amp;nbsp;_RTL_VERIFIER_THUNK_DESCRIPTOR&amp;nbsp;{
&amp;nbsp;&amp;nbsp;PCHAR&amp;nbsp;ThunkName;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;ThunkOldAddress;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;ThunkNewAddress;
}&amp;nbsp;RTL_VERIFIER_THUNK_DESCRIPTOR,&amp;nbsp;*PRTL_VERIFIER_THUNK_DESCRIPTOR;

&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;struct&lt;/span&gt;&amp;nbsp;_RTL_VERIFIER_DLL_DESCRIPTOR&amp;nbsp;{
&amp;nbsp;&amp;nbsp;PWCHAR&amp;nbsp;DllName;
&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;DllFlags;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;DllAddress;
&amp;nbsp;&amp;nbsp;PRTL_VERIFIER_THUNK_DESCRIPTOR&amp;nbsp;DllThunks;
}&amp;nbsp;RTL_VERIFIER_DLL_DESCRIPTOR,&amp;nbsp;*PRTL_VERIFIER_DLL_DESCRIPTOR;

&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;struct&lt;/span&gt;&amp;nbsp;_RTL_VERIFIER_PROVIDER_DESCRIPTOR&amp;nbsp;{
&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;Length;
&amp;nbsp;&amp;nbsp;PRTL_VERIFIER_DLL_DESCRIPTOR&amp;nbsp;ProviderDlls;
&amp;nbsp;&amp;nbsp;RTL_VERIFIER_DLL_LOAD_CALLBACK&amp;nbsp;ProviderDllLoadCallback;
&amp;nbsp;&amp;nbsp;RTL_VERIFIER_DLL_UNLOAD_CALLBACK&amp;nbsp;ProviderDllUnloadCallback;
&amp;nbsp;&amp;nbsp;PWSTR&amp;nbsp;VerifierImage;
&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;VerifierFlags;
&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;VerifierDebug;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;RtlpGetStackTraceAddress;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;RtlpDebugPageHeapCreate;
&amp;nbsp;&amp;nbsp;PVOID&amp;nbsp;RtlpDebugPageHeapDestroy;
&amp;nbsp;&amp;nbsp;RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK&amp;nbsp;ProviderNtdllHeapFreeCallback;
}&amp;nbsp;RTL_VERIFIER_PROVIDER_DESCRIPTOR,&amp;nbsp;*PRTL_VERIFIER_PROVIDER_DESCRIPTOR;

&lt;span style="color: green;"&gt;//&amp;nbsp;ntdll!DbgPrint&lt;/span&gt;
&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;ULONG&amp;nbsp;(&lt;span style="color: blue;"&gt;__cdecl&lt;/span&gt;*&amp;nbsp;PFN_DbgPrint)(PCH,&amp;nbsp;...);
PFN_DbgPrint&amp;nbsp;DbgPrint;

&lt;span style="color: green;"&gt;//&amp;nbsp;Here&amp;nbsp;we&amp;nbsp;go&lt;/span&gt;
&lt;span style="color: blue;"&gt;typedef&lt;/span&gt;&amp;nbsp;BOOL&amp;nbsp;(WINAPI*&amp;nbsp;PFN_CloseHandle)(HANDLE);
BOOL&amp;nbsp;WINAPI&amp;nbsp;ThunkCloseHandle(HANDLE&amp;nbsp;hObject);

&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;RTL_VERIFIER_THUNK_DESCRIPTOR&amp;nbsp;aThunks[]&amp;nbsp;=&amp;nbsp;{{&lt;span style="color: #a31515;"&gt;"CloseHandle"&lt;/span&gt;,&amp;nbsp;NULL,&amp;nbsp;ThunkCloseHandle},&amp;nbsp;{}};
&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;RTL_VERIFIER_DLL_DESCRIPTOR&amp;nbsp;aDlls[]&amp;nbsp;=&amp;nbsp;{{L&lt;span style="color: #a31515;"&gt;"kernel32.dll"&lt;/span&gt;,&amp;nbsp;0,&amp;nbsp;NULL,&amp;nbsp;aThunks},&amp;nbsp;{}};
&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;RTL_VERIFIER_PROVIDER_DESCRIPTOR&amp;nbsp;vpd&amp;nbsp;=&amp;nbsp;{&lt;span style="color: blue;"&gt;sizeof&lt;/span&gt;(RTL_VERIFIER_PROVIDER_DESCRIPTOR),&amp;nbsp;aDlls};

BOOL&amp;nbsp;WINAPI&amp;nbsp;ThunkCloseHandle(HANDLE&amp;nbsp;hObject)
{
&amp;nbsp;&amp;nbsp;BOOL&amp;nbsp;fRetVal&amp;nbsp;=&amp;nbsp;((PFN_CloseHandle)(aThunks[0].ThunkOldAddress))(hObject);
&amp;nbsp;&amp;nbsp;DbgPrint(&lt;span style="color: #a31515;"&gt;"CloseHandle(%p)&amp;nbsp;=&amp;nbsp;%s\n"&lt;/span&gt;,&amp;nbsp;hObject,&amp;nbsp;fRetVal&amp;nbsp;?&amp;nbsp;&lt;span style="color: #a31515;"&gt;"TRUE"&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color: #a31515;"&gt;"FALSE"&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;fRetVal;
}

BOOL&amp;nbsp;WINAPI&amp;nbsp;DllMain(HINSTANCE&amp;nbsp;hinstDLL,&amp;nbsp;DWORD&amp;nbsp;fdwReason,&amp;nbsp;PRTL_VERIFIER_PROVIDER_DESCRIPTOR*&amp;nbsp;pVPD)
{
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;switch&lt;/span&gt;(fdwReason)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;DLL_PROCESS_ATTACH:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;::DisableThreadLibraryCalls(hinstDLL);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;DLL_PROCESS_DETACH:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;case&lt;/span&gt;&amp;nbsp;DLL_PROCESS_VERIFIER:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DbgPrint&amp;nbsp;=&amp;nbsp;(PFN_DbgPrint)::GetProcAddress(::GetModuleHandle(TEXT(&lt;span style="color: #a31515;"&gt;"NTDLL"&lt;/span&gt;)),&amp;nbsp;&lt;span style="color: #a31515;"&gt;"DbgPrint"&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DbgPrint(&lt;span style="color: #a31515;"&gt;"CommandLine:&amp;nbsp;%s\n"&lt;/span&gt;,&amp;nbsp;::GetCommandLineA());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*pVPD&amp;nbsp;=&amp;nbsp;&amp;amp;vpd;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;default&lt;/span&gt;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;::DebugBreak(); &lt;span style="color: green;"&gt;// loader lock, be careful!!!&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;TRUE;
}
&lt;/pre&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;p&gt;To compile the source code, use the following command line:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;cl.exe avhook.cpp /D UNICODE /GS- /LD /Od /link /ENTRY:DllMain /NODEFAULTLIB /RELEASE /SUBSYSTEM:CONSOLE kernel32.lib&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Copy the generated avhook.dll&amp;nbsp;DLL to %windir%\system32 or %windir%\syswow64 folder, depending on the bitness,&amp;nbsp;and import the&amp;nbsp;IFEO entry into registry:&lt;/p&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\&lt;span style="color: #0000ff;"&gt;notepad.exe&lt;/span&gt;]
&lt;span style="color: #993300;"&gt;"VerifierDlls"&lt;span style="color: #000000;"&gt;=&lt;/span&gt;"avhook.dll"&lt;br /&gt;"GlobalFlag"&lt;span style="color: #000000;"&gt;=&lt;/span&gt;"0x100"&lt;/span&gt;&lt;span style="color: #993300;"&gt;&lt;/span&gt;
&lt;span style="color: #993300;"&gt;"VerifierFlags"&lt;/span&gt;=&lt;span style="color: #0000ff;"&gt;dword&lt;/span&gt;:&lt;span style="color: #993300;"&gt;80000000&lt;/span&gt;&lt;/pre&gt;
&lt;hr width="100%" style="width: 100%;" /&gt;
&lt;p&gt;Launch notepad.exe from debugger:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: verdana,geneva; font-size: small; background-color: #c0c0c0;"&gt;windbg.exe notepad.exe&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And here is what we got:&lt;/p&gt;
&lt;pre style="background: white; color: black; font-family: Consolas;"&gt;Executable search path is:
ModLoad: 00160000 00190000   notepad.exe
ModLoad: 77070000 771f0000   ntdll.dll
Page heap: pid 0x158C: page heap enabled with flags 0x2.
AVRF: notepad.exe: pid 0x158C: flags 0x48004: application verifier enabled
ModLoad: 714a0000 71500000   C:\Windows\syswow64\&lt;span style="color: #0000ff;"&gt;verifier.dll &lt;/span&gt;Page heap: pid 0x158C: page heap enabled with flags 0x2.
AVRF: notepad.exe: pid 0x158C: flags 0x48004: application verifier enabled
ModLoad: 715c0000 715c5000   &lt;span style="color: #0000ff;"&gt;C:\Windows\SysWOW64\hook.dll &lt;/span&gt;
...

&lt;span style="background-color: #ffff99;"&gt;CloseHandle(00000320) = TRUE&lt;br /&gt;CloseHandle(0000032C) = TRUE&lt;br /&gt;CloseHandle(00000330) = TRUE&lt;br /&gt;CloseHandle(0000034C) = TRUE&lt;br /&gt;CloseHandle(00000328) = TRUE&lt;br /&gt;CloseHandle(000001C8) = TRUE&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;As you could see, our provider DLL is working as expected :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10340995" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/reiley/archive/tags/WinDBG/">WinDBG</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/IFEO/">IFEO</category><category domain="http://blogs.msdn.com/b/reiley/archive/tags/AppVerifier/">AppVerifier</category></item></channel></rss>