<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.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>Mark's Blog</title><link>http://blogs.technet.com/markrussinovich/default.aspx</link><description>Mark Russinovich's technical blog covering topics such as Windows troubleshooting, technologies and security.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>The Case of the Slow Logons</title><link>http://blogs.technet.com/markrussinovich/archive/2010/01/13/3305263.aspx</link><pubDate>Wed, 13 Jan 2010 03:06:50 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3305263</guid><dc:creator>markrussinovich</dc:creator><slash:comments>48</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3305263.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3305263</wfw:commentRss><description>Emails containing troubleshooting cases keep arriving in my inbox. I’ve received many cases that start with a seemingly unsolvable problem and end a few steps later with a solution or - often just as useful - a workaround. I’ve amassed several hundred...(&lt;a href="http://blogs.technet.com/markrussinovich/archive/2010/01/13/3305263.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3305263" width="1" height="1"&gt;</description></item><item><title>The Machine SID Duplication Myth</title><link>http://blogs.technet.com/markrussinovich/archive/2009/11/03/3291024.aspx</link><pubDate>Tue, 03 Nov 2009 08:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3291024</guid><dc:creator>markrussinovich</dc:creator><slash:comments>234</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3291024.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3291024</wfw:commentRss><description>On November 3 2009, Sysinternals retired NewSID , a utility that changes a computers machine Security Identifier (machine SID). I wrote NewSID in 1997 (its original name was NTSID) because the only tool available at the time for changing machine SIDs...(&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/11/03/3291024.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3291024" width="1" height="1"&gt;</description></item><item><title>Channel 9: Inside Windows 7 Redux</title><link>http://blogs.technet.com/markrussinovich/archive/2009/10/22/3288577.aspx</link><pubDate>Thu, 22 Oct 2009 14:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3288577</guid><dc:creator>markrussinovich</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3288577.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3288577</wfw:commentRss><description>Windows 7 hit general availability today, putting it in stores and on new PC’s. There are plenty of beneath-the-surface changes that make Windows 7 more power efficient, scalable, secure and responsive (and of course, there are lots of user-visible features...(&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/10/22/3288577.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3288577" width="1" height="1"&gt;</description></item><item><title>Recent and Upcoming Speaking Engagements</title><link>http://blogs.technet.com/markrussinovich/archive/2009/10/08/3285676.aspx</link><pubDate>Thu, 08 Oct 2009 18:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3285676</guid><dc:creator>markrussinovich</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3285676.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3285676</wfw:commentRss><description>&lt;p&gt;I wanted to update you on my recent and upcoming speaking engagements. First, I’ve been hosting a series of virtual roundtables for the &lt;a href="http://technet.microsoft.com/en-us/windows/default.aspx"&gt;Springboard Series&lt;/a&gt; program. Springboard’s purpose is to provide a one-stop resource for IT Pros evaluating, deploying and managing Windows. The most recent roundtable, which took place at the end of September, focused on virtualization technologies such as App-V, XP Mode, MEDV, and Remote Desktop Sessions, and how you can use them to address application compatibility as you move from Windows XP to Windows Vista or Windows 7. At the table we had Microsoft application compatibility experts and industry partners and it was another great discussion of the issues and tradeoffs of various approaches. Check out the recording &lt;a href="http://technet.microsoft.com/en-us/windows/ee532933.aspx?ITPID=istream"&gt;here&lt;/a&gt; and the previous roundtables &lt;a href="http://talkingaboutwindows.com/virtual-round-table.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;On September 22 I delivered a session at the &lt;a href="http://www.intel.com/idf/"&gt;Intel Developer Forum&lt;/a&gt; (IDF) in San Francisco with Shiv Kaushik, an Intel Fellow, on how Microsoft and Intel collaborated during this release cycle to make sure that Windows takes advantage of innovations delivered by new Intel hardware, specifically the Nehalem platform. You can watch the presentation free on Intel’s IDF site &lt;a href="http://intelstudios.edgesuite.net/idf/2009/sf/ti/day1/ss/f.htm"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;In November I’ll be speaking at &lt;a href="http://www.microsoft.com/europe/teched/"&gt;TechEd Europe&lt;/a&gt; in Berlin and the &lt;a href="http://microsoftpdc.com/"&gt;Professional Developer’s Conference&lt;/a&gt; in Los Angeles. I’m delivering four sessions at TechEd, two of which, the Case of the Unexplained and Pushing the Limits of Windows, are based on blog post series I’ve been running: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Windows 7 and Windows Server 2008 R2 Kernel Changes        &lt;br /&gt;&lt;/strong&gt;This session goes beneath the hood of Windows 7 and Windows Server 2008 R2 to describe and demonstrate the key changes in the kernel. Topics include: scalability improvements (such as removal of the global scheduler lock, support for more than 64 logical processors, and user mode scheduling), core parking and timer coalescing for power efficiency, trigger-started services, improved multi-function device support, core architecture changes to modularize Windows (&amp;quot;Minwin&amp;quot;) and more. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Case of the Unexplained 2009...Windows Troubleshooting with Mark Russinovich        &lt;br /&gt;&lt;/strong&gt;Come hear Mark Russinovich, the master of Windows troubleshooting, walk you through step by step how he has solved seemingly unsolvable system and application problems on Windows. With all new real case studies, Mark will show how to apply the Microsoft Debugging Tools and his own Sysinternals tools, including Process Explorer, Process Monitor, and Accesschk, to solve system crashes, process hangs, security vulnerabilities, DLL conflicts, permissions problems, registry misconfiguration, network hangs, and file system issues. These tools are used on a daily basis by Microsoft Product Support and have been used effectively to solve a wide variety of desktop and server issues, so being familiar with their operation and application will assist you in dealing with different problems on Windows. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Pushing the Limits of Windows        &lt;br /&gt;&lt;/strong&gt;How many processes, threads, and handles can you make?&amp;#160; How does Windows react when it's pushed to the limit? This session goes deep into the kernel to explain what limits Windows from creating more processes, threads, handles, and what the real limits are for physical and virtual memory. How much more can you do with 64-bits? Live demos show the effect on Windows when various resources are exhausted. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Windows and Malware: Which Features are Security and Which Aren’t        &lt;br /&gt;&lt;/strong&gt;This session goes under the hood of a number of Windows features that all have the common trait of looking and smelling like security to present their true purpose and value. Learn which of technologies like Kernel Patch Protection, UAC elevations, Protected Mode Internet Security, Service isolation, Code Integrity, and virtual machines really make security guarantees and which are really designed to solve other problems. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;At the &lt;a href="http://microsoftpdc.com/"&gt;PDC&lt;/a&gt;, I’ll be delivering the &lt;a href="http://microsoftpdc.com/Sessions/P09-20"&gt;kernel changes talk&lt;/a&gt; and participating in the kernel portion of a Windows 7 boot camp pre-conference that’s free to everyone, whether you’re attending the PDC or not. Joining me will be Memory Manager architect &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Landy-Wang-Windows-Memory-Manager/"&gt;Landy Wang&lt;/a&gt; and Windows Kernel architect &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Arun-Kishan-Farewell-to-the-Windows-Kernel-Dispatcher-Lock/"&gt;Arun Kishan&lt;/a&gt; (who brought us great scalability in Windows Server 2008 R2 by removing the kernel’s dispatcher lock). You can find out more &lt;a href="http://microsoftpdc.com/Sessions/WKSP08"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;I look forward to seeing you at one of my sessions!&lt;/p&gt;  &lt;p&gt;Finally, a little off-topic, but I’ve signed up for Twitter and am shooting to be the anti-Ashton Kutcher. Actually, I’m setting my sites a little lower: I want to be the first user to get to 10,000 followers without ever tweeting or following anyone else (in other words, not using Twitter at all). Sign up to follow me &lt;a href="http://twitter.com/MarkRussinovich"&gt;here&lt;/a&gt;!&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3285676" width="1" height="1"&gt;</description></item><item><title>Pushing the Limits of Windows: Handles</title><link>http://blogs.technet.com/markrussinovich/archive/2009/09/29/3283844.aspx</link><pubDate>Tue, 29 Sep 2009 19:04:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3283844</guid><dc:creator>markrussinovich</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3283844.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3283844</wfw:commentRss><description>&lt;p&gt;This is the fifth post in my &lt;strong&gt;Pushing the Limits of Windows&lt;/strong&gt; series where I explore the upper bound on the number and size of resources that Windows manages, such as physical memory, virtual memory, processes and threads:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx" mce_href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx"&gt;Pushing the Limits of Windows: Physical Memory&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx" mce_href="http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx"&gt;Pushing the Limits of Windows: Virtual Memory&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx" mce_href="http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx"&gt;Pushing the Limits of Windows: Paged and Nonpaged Pool&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx" mce_href="http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx"&gt;Pushing the Limits of Windows: Processes and Threads&lt;/a&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This time I’m going to go inside the implementation of handles to find and explain their limits. Handles are data structures that represent open instances of basic operating system objects applications interact with, such as files, registry keys, synchronization primitives, and shared memory. There are two limits related to the number of handles a process can create: the maximum number of handles the system sets for a process and the amount of memory available to store the handles and the objects the application is referencing with its handles. &lt;/p&gt;  &lt;p&gt;In most cases the limits on handles are far beyond what typical applications or a system ever use. However, applications not designed with the limits in mind may push them in ways their developers don’t anticipate. A more common class of problems arise because the lifetime of these resources must be managed by applications and, just like for virtual memory, resource lifetime management is challenging even for the best developers. An application that fails to release unneeded resources causes a leak of the resource that can ultimately cause a limit to be hit, resulting in bizarre and difficult to diagnose behaviors for the application, other applications or the system in general.&amp;#160; &lt;/p&gt;  &lt;p&gt;As always, I recommend you read the previous posts because they explain some of the concepts&amp;#160; this post references, like paged pool. &lt;/p&gt;  &lt;h4&gt;Handles and Objects&lt;/h4&gt;  &lt;p&gt;The kernel-mode core of Windows, which is implemented in the %SystemRoot%\System32\Ntoskrnl.exe image, consists of various subsystems such as the Memory Manager, Process Manager, I/O Manager, Configuration Manager (registry), which are all parts of the Executive. Each of these subsystems defines one or more types with the Object Manager to represent the resources they expose to applications. For example, the Configuration Manager defines the &lt;em&gt;key &lt;/em&gt;object to represent an open registry key; the memory manager defines the &lt;em&gt;Section &lt;/em&gt;object for shared memory; the Executive defines S&lt;em&gt;emaphore&lt;/em&gt;, M&lt;em&gt;utant&lt;/em&gt; (the internal name for a mutex), and&amp;#160; &lt;em&gt;Event &lt;/em&gt;synchronization objects (these objects wrap fundamental data structures defined by the operating system’s Kernel subsystem); the I/O Manager defines the &lt;em&gt;File&lt;/em&gt; object to represent open instances of device driver resources, which include file system files; and the Process Manager the creates &lt;em&gt;Thread &lt;/em&gt;and &lt;em&gt;Process &lt;/em&gt;objects I discussed in my last Pushing the Limits post. Every release of Windows introduces new object types with Windows 7 defining a total of 42. You can see the objects defined by running the Sysinternals &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896657.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb896657.aspx"&gt;Winobj&lt;/a&gt; utility with administrative rights and navigating to the ObjectTypes directory in the Object Manager namespace:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_40.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_40.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_18.png" width="304" height="377" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_18.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When an application wants to manage one of these resources it first must call the appropriate API to create or open the resource. For instance, the &lt;a href="http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx"&gt;CreateFile&lt;/a&gt; function opens or creates a file, the &lt;a href="http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx"&gt;RegOpenKeyEx&lt;/a&gt; function opens a registry key, and the &lt;a href="http://msdn.microsoft.com/en-us/library/ms682446(vs.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms682446(vs.85).aspx"&gt;CreateSemaphoreEx&lt;/a&gt; function opens or creates a semaphore. If the function succeeds, Windows allocates a &lt;em&gt;handle &lt;/em&gt;in the &lt;em&gt;handle table&lt;/em&gt; of the application’s process and returns the handle value, which applications treat as opaque but that is actually the index of the returned handle in the handle table. &lt;/p&gt;  &lt;p&gt;With the handle in hand, the application then queries or manipulates the object by passing the handle value to subsequent API functions like &lt;a href="http://msdn.microsoft.com/en-us/library/aa365467(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa365467(VS.85).aspx"&gt;ReadFile&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx"&gt;SetEvent&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ms686277(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms686277(VS.85).aspx"&gt;SetThreadPriority&lt;/a&gt;, and &lt;a href="http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx"&gt;MapViewOfFile&lt;/a&gt;. The system can look up the object the handle refers to by indexing into the handle table to locate the corresponding handle entry, which contains a pointer to the object. The handle entry also stores the accesses the process was granted at the time it opened the object, which enables the system to make sure it doesn’t allow the process to perform an operation on the object for which it didn’t ask permission. For example, if the process successfully opened a file for read access, the handle entry would look like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_42.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_42.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_19.png" width="380" height="271" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_19.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If the process tried to write to the file, the function would fail because the access hadn’t been granted and the cached read access means that the system doesn’t have to execute a more expensive access-check again. &lt;/p&gt;  &lt;h4&gt;Maximum Number of Handles&lt;/h4&gt;  &lt;p&gt;You can explore the first limit with the Testlimit tool I’ve been using in this series to empirically explore limits. It’s available for download on the Windows Internals book page &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;here&lt;/a&gt;. To test the number of handles a process can create, Testlimit implements the –h switch that directs it to create as many handles as possible. It does so by creating an event object with &lt;a href="http://msdn.microsoft.com/en-us/library/ms682396(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms682396(VS.85).aspx"&gt;CreateEvent&lt;/a&gt; and then repeatedly duplicating the handle the system returns using &lt;a href="http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx"&gt;DuplicateHandle&lt;/a&gt;. By duplicating the handle, Testlimit avoids creating new events and the only resources it consumes are those for the handle table entries. Here’s the result of Testlimit with the –h option on a 64-bit system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_2.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb.png" width="374" height="107" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The result doesn’t represent the total number of handles a process can create, however, because system DLLs open various objects during process initialization. You see a process’s total handle count by adding a handle count column to Task Manager or Process Explorer. The total shown for Testlimit in this case is 16,711,680:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_6.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_2.png" width="197" height="58" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_2.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When you run Testlimit on a 32-bit system, the number of handles it can create is slightly different:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_8.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_3.png" width="554" height="115" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_3.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Its total handle count is also different, 16,744,448:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_10.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_4.png" width="190" height="44" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_4.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Where do the differences come from? The answer lies in the way that the Executive, which is responsible for managing handle tables, sets the per-process handle limit, as well as the size of a handle table entry. In one of the rare cases where Windows sets a hard-coded upper limit on a resource, the Executive defines 16,777,216 (16*1024*1024) as the maximum number of handles a process can allocate. Any process that has more than a ten thousand handles open at any given point in time is likely either poorly designed or has a handle leak, so a limit of 16 million is essentially infinite and can simply help prevent a process with a leak from impacting the rest of the system. Understanding why the numbers Task Manager shows don’t equal the hard-coded maximum requires a look at the way the Executive organizes handle tables.&lt;/p&gt;  &lt;p&gt;A handle table entry must be large enough to store the granted-access mask and an object pointer. The access mask is 32-bits, but the pointer size obviously depends on whether it’s a 32-bit or 64-bit system. Thus, a handle entry is 8-bytes on 32-bit Windows and 12-bytes on 64-bit Windows. 64-bit Windows aligns the handle entry data structure on 64-bit boundaries, so a 64-bit handle entry actually consumes 16-bytes. Here’s the definition for a handle entry on 64-bit Windows, as shown in a kernel debugger using the dt (dump type) command:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_18.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_18.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_7.png" width="484" height="140" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_7.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The output reveals that the structure is actually a union that can sometimes store information other than an object pointer and access mask, but those two fields are highlighted. &lt;/p&gt;  &lt;p&gt;The Executive allocates handle tables on demand in page-sized blocks that it divides into handle table entries. That means a page, which is 4096 bytes on both x86 and x64, can store 512 entries on 32-bit Windows and 256 entries on 64-bit Windows. The Executive determines the maximum number of pages to allocate for handle entries by dividing the hard-coded maximum,16,777,216, by the number of handle entries in a page, which results on 32-bit Windows to 32,768 and on 64-bit Windows to 65,536. Because the Executive uses the first entry of each page for its own tracking information, the number of handles available to a process is actually 16,777,216 minus those numbers, which explains the results obtained by Testlimit: 16,777,216-65,536 is 16,711,680 and 16,777,216-65,536-32,768 is 16,744,448.&lt;/p&gt;  &lt;h4&gt;Handles and Paged Pool&lt;/h4&gt;  &lt;p&gt;The second limit affecting handles is the amount of memory required to store handle tables, which the Executive allocates from paged pool. The Executive uses a three-level scheme, similar to the way that processor Memory Management Units (MMUs) manage virtual to physical address translations, to keep track of the handle table pages that it allocates. We’ve already seen the organization of the lowest and mid levels, which store actual handle table entries. The top level serves as pointers into the mid-level tables and includes 1024 entries per-page on 32-bit Windows. The total number of pages required to store the maximum number of handles can therefore be calculated for 32-bit Windows as 16,777,216/512*4096, which is 128MB. That’s consistent with the paged pool usage of Testlimit as shown in Task Manager:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_12.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_5.png" width="184" height="46" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_5.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On 64-bit Windows, there are 256 pointers in a page of top-level pointers. That means the total paged pool usage for a full handle table is 16,777,216/256*4096, which is 256MB. A look at Testlimit’s paged pool usage on 64-bit Windows confirms the calculation:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_14.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_6.png" width="188" height="42" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_6.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Paged pool is generally large enough to more than accommodate those sizes, but as I stated earlier, a process that creates that many handles is almost certainly going to exhaust other resources, and if it reaches the per-process handle limit it will probably fail itself because it can’t open any other objects. &lt;/p&gt;  &lt;h4&gt;Handle Leaks&lt;/h4&gt;  &lt;p&gt;A handle leaker will have a handle count that rises over time. The reason that a handle leak is so insidious is that unlike the handles Testlimit creates, which all point to the same object, a process leaking handles is probably leaking objects as well. For example, if a process creates events but fails to close them, it will leak both handle entries and event objects. Event objects consume nonpaged pool, so the leak will impact nonpaged pool in addition to paged pool. &lt;/p&gt;  &lt;p&gt;You can graphically spot the objects a process is leaking using Process Explorer’s handle view because it highlights new handles in green and closed handles in red; if you see lots of green with infrequent red then you might be seeing a leak. You can watch Process Explorer’s handle highlighting in action by opening a Command Prompt process, selecting the process in Process Explorer, opening the handle-view lower pane and then changing directory in the Command Prompt. The old working directory’s handle will highlight in red and the new one in green:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_20.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_20.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_8.png" width="277" height="137" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_8.png" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;By default, Process Explorer only shows handles that reference objects that have names, which means that you won’t see all the handles a process is using unless you select &lt;em&gt;Show Unnamed Handles and Mappings&lt;/em&gt; from the View menu. Here are some of the unnamed handles in Command Prompt’s handle table:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_32.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_32.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_14.png" width="384" height="144" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_14.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Just like most bugs, only the developer of the code that’s leaking can fix it. If you spot a leak in a process that can host multiple components or extensions, like Explorer, a Service Host or Internet Explorer, then the question is what component is the one responsible for the leak. Figuring that out might enable you to avoid the problem by disabling or uninstalling the problematic extension, fix the problem by checking for an update, or report the bug to the vendor. &lt;/p&gt;  &lt;p&gt;Fortunately, Windows includes a handle tracing facility that you can use to help identify leaks and the responsible software. It’s enabled on a per-process basis and when active causes the Executive to record a stack trace at the time every handle is created or closed. You can enable it either by using the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c4a25ab9-649d-4a1b-b4a7-c9d8b095df18&amp;amp;DisplayLang=en#filelist" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c4a25ab9-649d-4a1b-b4a7-c9d8b095df18&amp;amp;DisplayLang=en#filelist"&gt;Application Verifier&lt;/a&gt;, a free download from Microsoft, or by using the &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx" mce_href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;Windows &lt;font color="#acb613"&gt;D&lt;/font&gt;ebugger&lt;/a&gt; (Windbg). You should use the Application Verifier if you want the system to track a process’s handle activity from when it starts. In either case, you’ll need to use a debugger and the &lt;a href="http://msdn.microsoft.com/en-us/library/cc266932.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc266932.aspx"&gt;!htrace&lt;/a&gt; debugger command to view the trace information. &lt;/p&gt;  &lt;p&gt;To demonstrate the tracing in action, I launched Windbg and attached to the Command Prompt I had opened earlier. I then executed the !htrace command with the -&lt;em&gt;enable &lt;/em&gt;switch to turn on handle tracing:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_44.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_44.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_20.png" width="464" height="102" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_20.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I let the process’s execution continue and changed directory again. Then I switched back to Windbg, stopped the process’s execution, and executed htrace without any options, which has it list all the open and close operations the process executed since the previous !htrace snapshot (created with the &lt;em&gt;–snapshot &lt;/em&gt;option) or from when handle tracing was enabled. Here’s the output of the command for the same session:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_36.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_36.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_16.png" width="554" height="830" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_16.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The events are printed from most recent operation to least, so reading from the bottom, Command Prompt opened handle 0xb8, then closed it, next opened handle 0x22c, and finally closed handle 0xec. Process Explorer would show handle 0x22c in green and 0xec in red if it was refreshed after the directory change, but probably wouldn’t see 0xb8 unless it happened to refresh between the open and close of that handle. The stack for 0x22c’s open reveals that it was the result of Command Prompt (cmd.exe) executing its ChangeDirectory function. Adding the handle value column to Process Explorer confirms that the new handle is 0x22c:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_38.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_38.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_17.png" width="234" height="76" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_17.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you’re just looking for leaks, you should use !htrace with the &lt;em&gt;–diff &lt;/em&gt;switch, which has it show only new handles since the last snapshot or start of tracing. Executing that command shows just handle 0x22c, as expected:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_34.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_34.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_15.png" width="554" height="255" mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsHandlesGDIObjec_C315/image_thumb_15.png" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Finally, a great video that presents more tips for debugging handle leaks is this Channel 9 interview with Jeff Dailey, a Microsoft Escalation Engineer that debugs them for a living: &lt;a title="http://channel9.msdn.com/posts/jeff_dailey/Understanding-handle-leaks-and-how-to-use-htrace-to-find-them/" href="http://channel9.msdn.com/posts/jeff_dailey/Understanding-handle-leaks-and-how-to-use-htrace-to-find-them/" mce_href="http://channel9.msdn.com/posts/jeff_dailey/Understanding-handle-leaks-and-how-to-use-htrace-to-find-them/"&gt;http://channel9.msdn.com/posts/jeff_dailey/Understanding-handle-leaks-and-how-to-use-htrace-to-find-them/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next time I’ll look at limits for a couple of other handle-based resources, GDI Object and USER Objects. Handles to those resources are managed by the Windows subsystem, not the Executive, so use different resources and have different limits. &lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3283844" width="1" height="1"&gt;</description></item><item><title>The Case of the Temporary Registry Profiles</title><link>http://blogs.technet.com/markrussinovich/archive/2009/08/10/3272210.aspx</link><pubDate>Mon, 10 Aug 2009 19:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3272210</guid><dc:creator>markrussinovich</dc:creator><slash:comments>68</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3272210.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3272210</wfw:commentRss><description>&lt;p&gt;Microsoft Customer Support Services (CSS) is one of the biggest customers of the Sysinternals tools and they often send me interesting cases they’ve solved with them. This particular case is especially interesting because it affected a large number of users and the troubleshooting process made use of one of &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor’s&lt;/a&gt; lesser-known features. The case opened when a customer contacted Microsoft support reporting that several of their users would occasionally get this error message when loggging on to their systems:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_thumb_2.png" width="324" height="161" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This caused Windows to create a temporary profile for the user’s logon session. A user profile consists of a directory, %UserProfile%, into which applications save user-specific configuration and data files, as well as a registry hive file stored in that directory, %UserProfile%\Ntuser.dat, that the Winlogon process loads when the user logs in. Applications store user settings in the registry hive by calling registry functions that refer to the HKEY_CURRENT_USER (HKCU) root key. The user’s loss of access to their profile made the problem critical, because whenever that happened, the user would apparently lose all their settings and access to files stored in their profile directory. In most cases, users contacted the company’s support desk, which would ask the user to try rebooting and logging in until the problem resolved itself. &lt;/p&gt;  &lt;p&gt;As with all cases, Microsoft support began by asking about the system configuration, inventory of installed software, and about any recent changes the company had made to their systems. In this case, the fact that stood out was that all the systems on which the problem had occurred had recently been upgraded to a new version of Citrix Corporation's ICA client, a remote desktop application. Microsoft contacted Citrix support to see if they knew of any issues with the new client. They didn’t, but said they would investigate. &lt;/p&gt;  &lt;p&gt;Unsure whether the ICA client upgrade was responsible for the profile problem, Microsoft support instructed the customer to enable profile logging, which you can do by configuring a registry key as per this Knowledge Base article: &lt;a href="http://support.microsoft.com/kb/221833"&gt;How to enable user environment debug logging in retail builds of Windows&lt;/a&gt;. The customer pushed a script out to their systems to make the required registry changes and shortly after got another call from a user with the profile problem. They grabbed a copy of the profile log off the system from %SystemRoot%\Debug\UserMode\Userenv.log and sent it into Microsoft. The log was inconclusive, but did provide an important clue: it indicated that the user’s profile had failed to load because of error 32, which is &lt;a href="http://support.microsoft.com/kb/316609"&gt;ERROR_SHARING_VIOLATION&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_thumb.png" width="554" height="70" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When a process opens a file, it specifies what kinds of sharing it allows for the file. If it is writing to the file it may allow other processes to read from the file, for example, but not to also write to the file. The sharing violation in the log file meant that another process had opened the user’s registry hive in a way that was incompatible with the way that the logon process wanted to open the file. &lt;/p&gt;  &lt;p&gt;In the meantime, more customers around the world began contacting Microsoft and Citrix with the same issue, all had also deployed the new ICA client. Citrix support then reported that they suspected that the sharing violation might be caused by one of the ICA client’s processes, Ssonvr.exe. During installation, the ICA client registers a Network Provider DLL (Pnsson.dll) that the Windows Multiple Provider Notification Application (%SystemRoot%\System32\Mpnotify.exe) calls when the system boots. Mpnotify.exe is itself launched at logon by the Winlogon process.The Citrix notification DLL launches the Ssonvr.exe process asynchronous to the user’s logon:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_15.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_thumb_6.png" width="450" height="264" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The only problem with the theory was that Citrix developers insisted that the process did not attempt to load any user registry profile or even read any keys or values from one. Both Microsoft and Citrix were stumped. &lt;/p&gt;  &lt;p&gt;Microsoft created a version of Winlogon and the kernel with additional diagnostic information and tried to reproduce the problem on lab systems configured identically to the client’s, but without success. The customer couldn’t even reproduce the problem with the modified Windows images, presumably because the images changed the timing of the system enough to avoid the problem. At this point a Microsoft support engineer suggested that the customer capture a trace of logon activity with Process Monitor. &lt;/p&gt;  &lt;p&gt;There are a couple of ways to configure Process Monitor to record logon operations: one is to use &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx"&gt;Sysinternals PsExec&lt;/a&gt; to launch it in the session 0 so that it survives the logoff and subsequent logon and another is to use the boot logging feature to capture activity from early in the boot, including the logon. The engineer chose the latter, so he told the customer to run Process Monitor on one of the system’s that persistently exhibited the problem, select Enable Boot Logging from the Process Monitor Options menu, and reboot, repeating the steps until the problem reproduced. This procedure configures the Process Monitor driver to load early in the boot process and log activity to %SystemRoot%\Procmon.pmb. Once the user logged encountered the issue, they were to run Process Monitor again, at which point the driver would stop logging and Process Monitor would offer to convert the boot log into a standard Process Monitor log file. &lt;/p&gt;  &lt;p&gt;After a couple of attempts the user captured a boot log file that they submitted to Microsoft. Microsoft support engineers scanned through the log and came across the sharing violation error when Winlogon tried to load the user’s registry hive:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_thumb_3.png" width="554" height="114" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It was obvious from operations immediately preceding the error that Ssonsvr.exe was the process that had the hive opened. The question was, why was Ssonsvr.exe opening the registry hive? To answer that question the engineers turned to Process Monitor’s stack trace functionality. Process Monitor captures a call stack for every operation, which represents the function call nesting responsible for the operation. By looking at a call stack you can often determine an operation’s root cause when it might not be obvious just from the process that executed it. For example, the stack shows you if a DLL loaded into the process executed the operation and, if you have symbols configured and the call originates in a Windows image or other image for which you have symbols, it will even show you the names of the responsible functions. &lt;/p&gt;  &lt;p&gt;The stack for Ssonsvr.exe’s open of the Ntuser.dat file showed that Ssonsvr.exe wasn’t actually responsible for the operation, the Windows Logical Prefetcher was:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheNewLogonRegistryProfiles_DF02/image_thumb_4.png" width="429" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Introduced in Windows XP, the Logical Prefetcher is a kernel component that monitors the first ten seconds of a process launch, recording the directories and portions of files accessed by the process during that time to a file it stores in %SystemRoot%\Prefetch. So that multiple executables with the same name but in different directories get their own prefetch file, the Logical Prefetcher gives the file a name that’s a concatenation of the executable image name and the hash of the path in which the image is stored e.g. NOTEPAD.EXE-D8414F97.pf. You can actually see the files and directories the Logical Prefetcher saw an application reference the last time it launched by using the Sysinternals &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx"&gt;Strings&lt;/a&gt; utility to scan a prefetch file like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;strings &amp;lt;prefetch file&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The next time the application launches, the Logical Prefetcher, executing in the context of the process’s first thread, looks for a prefetch file. If one exists, it opens each directory it lists to bring the directory’s metadata into memory if not already present. The Logical Prefetcher then maps each file listed in the prefetch file and references the portions accessed the last time the application ran so that they also get brought into memory. The Logical Prefetcher can speed up an application launch because it generates large, sequential I/Os instead of issuing small random accesses to file data as the application would typically do during startup. &lt;/p&gt;  &lt;p&gt;The implication of the Logical Prefetcher in the profile problem only raised more questions, however. Why was it prefetching the user’s hive file in the context of Ssonsvr.exe when Ssonsvr.exe itself never accesses registry profiles? Microsoft support contacted the Logical Prefetcher’s development team for the answer. The developers first noted that the registry on Windows XP is read into memory using cached file I/O operations, which means that the Cache Manager’s read-ahead thread will proactively read portions of the hive. Since the read-ahead thread executes in the System process, and the Logical Prefetcher associates System process activity with the currently launching process, that a specific timing sequence of process launches and activity during the boot and log on could cause hive accesses to be seen by the Logical Prefetcher as being part of the Ssonsvr.exe launch. If the order was slightly different the next boot and log on, Winlogon might collide with the Logical Prefetcher, as seen in the captured boot log. &lt;/p&gt;  &lt;p&gt;The Logical Prefetcher is supposed to execute transparently to other activity on a system, but its file references can lead to sharing violations like this on Windows XP systems (on server systems the Logical Prefetcher only prefetches boot activity, and it does so synchronously before the boot process proceeds). For that reason, on Windows Vista and Windows 7 systems, the Logical Prefetcher makes use of a file system minifilter driver, Fileinfo (%SystemRoot%\System32\Drivers\Fileinfo.sys), to watch for potential sharing violation collisions and prevent them by stalling a second open operation on a file being accessed by the Logical Prefetcher until the Logical Prefetcher closes the file. &lt;/p&gt;  &lt;p&gt;Now that the problem was understood, Microsoft and Citrix brainstormed on workarounds customers could apply while Citrix worked on an update to the ICA Client that would prevent the sharing violation. One workaround was to disable application prefetching and another was to write a logoff script that deletes the Ssonsvr.exe prefetch files. Citrix published the workarounds in this &lt;a href="http://support.citrix.com/article/CTX118226"&gt;Citrix Knowledge Base&lt;/a&gt; article and Microsoft in this &lt;a href="http://support.microsoft.com/kb/969100/en-us"&gt;Microsoft Knowledge Base&lt;/a&gt; article. The update to the ICA Client, which was made available a few days later, changed the network provider DLL to 10 seconds after Ssonsvr.exe launches before returning control to Mpnotify.exe. Because Winlogon waits for Mpnotify to exit before logging on a user, the Logical Prefetcher won’t associate Winlogon’s accesses of the user’s hive with Ssonsvr.exe’s startup. &lt;/p&gt;  &lt;p&gt;As I said in the introduction, I find this case particularly interesting because it demonstrates a little known Process Monitor feature, boot logging, and the power of stack traces for root cause analysis, two key tools for everyone’s troubleshooting arsenal. It also shows how successful troubleshooting sometimes means coming up with a workaround when there’s no fix or you must wait until a vendor provides one. Another case successfully closed with Process Monitor! Please keep sending me screen shots and log files of the cases you solve. &lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3272210" width="1" height="1"&gt;</description></item><item><title>Pushing the Limits of Windows: Processes and Threads</title><link>http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx</link><pubDate>Wed, 08 Jul 2009 09:21:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3261309</guid><dc:creator>markrussinovich</dc:creator><slash:comments>39</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3261309.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3261309</wfw:commentRss><description>&lt;p&gt;This is the fourth post in my Pushing the Limits of Windows series that explores the boundaries of fundamental resources in Windows. This time, I’m going to discuss the limits on the maximum number of threads and processes supported on Windows. I’ll briefly describe the difference between a thread and a process, survey thread limits and then investigate process limits. I cover thread limits first since every active process has at least one thread (a process that’s terminated, but is kept referenced by a handle owned by another process won’t have any), so the limit on processes is directly affected by the caps that limit threads. &lt;/p&gt;  &lt;p&gt;Unlike some UNIX variants, most resources in Windows have no fixed upper bound compiled into the operating system, but rather derive their limits based on basic operating system resources that I’ve already covered. Process and threads, for example, require physical memory, virtual memory, and pool memory, so the number of processes or threads that can be created on a given Windows system is ultimately determined by one of these resources, depending on the way that the processes or threads are created and which constraint is hit first. I therefore recommend that you read the preceding posts if you haven’t, because I’ll be referring to reserved memory, committed memory, the system commit limit and other concepts I’ve covered:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx"&gt;Pushing the Limits of Windows: Physical Memory&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx"&gt;Pushing the Limits of Windows: Virtual Memory&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx"&gt;Pushing the Limits of Windows: Paged and Nonpaged Pool&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Processes and Threads&lt;/h3&gt;  &lt;p&gt;A Windows process is essentially container that hosts the execution of an executable image file. It is represented with a kernel process object and Windows uses the process object and its associated data structures to store and track information about the image’s execution. For example, a process has a virtual address space that holds the process’s private and shared data and into which the executable image and its associated DLLs are mapped. Windows records the process’s use of resources for accounting and query by diagnostic tools and it registers the process’s references to operating system objects in the process’s handle table. Processes operate with a security context, called a token, that identifies the user account, account groups, and privileges assigned to the process. &lt;/p&gt;  &lt;p&gt;Finally, a process includes one or more threads that actually execute the code in the process (technically, processes don’t run, threads do) and that are represented with kernel thread objects. There are several reasons applications create threads in addition to their default initial thread: processes with a user interface typically create threads to execute work so that the main thread remains responsive to user input and windowing commands; applications that want to take advantage of multiple processors for scalability or that want to continue executing while threads are tied up waiting for synchronous I/O operations to complete also benefit from multiple threads. &lt;/p&gt;  &lt;h3&gt;Thread Limits&lt;/h3&gt;  &lt;p&gt;Besides basic information about a thread, including its CPU register state, scheduling priority, and resource usage accounting, every thread has a portion of the process address space assigned to it, called a stack, which the thread can use as scratch storage as it executes program code to pass function parameters, maintain local variables, and save function return addresses. So that the system’s virtual memory isn’t unnecessarily wasted, only part of the stack is initially allocated, or committed and the rest is simply reserved. Because stacks grow downward in memory, the system places guard pages beyond the committed part of the stack that trigger an automatic commitment of additional memory (called a stack expansion) when accessed. This figure shows how a stack’s committed region grows down and the guard page moves when the stack expands, with a 32-bit address space as an example (not drawn to scale):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_thumb_1.png" width="320" height="346" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The Portable Executable (PE) structures of the executable image specify the amount of address space reserved and initially committed for a thread’s stack. The linker defaults to a reserve of 1MB and commit of one page (4K), but developers can override these values either by changing the PE values when they link their program or for an individual thread in a call to &lt;a href="http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx"&gt;CreateThread&lt;/a&gt;. You can use a tool like &lt;a href="http://msdn.microsoft.com/en-us/library/c1h23y6c(VS.71).aspx"&gt;Dumpbin&lt;/a&gt; that comes with Visual Studio to look at the settings for an executable. Here’s the Dumpbin output with the /headers option for the executable generated by a new Visual Studio project: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb.png" width="554" height="269" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Converting the numbers from hexadecimal, you can see the stack reserve size is 1MB and the initial commit is 4K and using the new Sysinternals &lt;a href="http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx"&gt;VMMap&lt;/a&gt; tool to attach to this process and view its address space, you can clearly see a thread stack’s initial committed page, a guard page, and the rest of the reserved stack memory:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_2.png" width="554" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Because each thread consumes part of a process’s address space, processes have a basic limit on the number of threads they can create that’s imposed by the size of their address space divided by the thread stack size.&lt;/p&gt;  &lt;h3&gt;32-bit Thread Limits&lt;/h3&gt;  &lt;p&gt;Even if the thread had no code or data and the entire address space could be used for stacks, a 32-bit process with the default 2GB address space could create at most 2,048 threads. Here’s the output of the &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;Testlimit&lt;/a&gt; tool running on 32-bit Windows with the –t switch (create threads) confirming that limit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_3.png" width="554" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Again, since part of the address space was already used by the code and initial heap, not all of the 2GB was available for thread stacks, thus the total threads created could not quite reach the theoretical limit of 2,048.&lt;/p&gt;  &lt;p&gt;I linked the Testlimit executable with the large address space-aware option, meaning that if it’s presented with more than 2GB of address space (for example on 32-bit systems booted with the /3GB or /USERVA Boot.ini option or its equivalent BCD option on Vista and later &lt;i&gt;increaseuserva&lt;/i&gt;), it will use it. 32-bit processes are given 4GB of address space when they run on 64-bit Windows, so how many threads can the 32-bit Testlimit create when run on 64-bit Windows? Based on what we’ve covered so far, the answer should be roughly 4096 (4GB divided by 1MB), but the number is actually significantly smaller. Here’s 32-bit Testlimit running on 64-bit Windows XP:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_4.png" width="554" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The reason for the discrepancy comes from the fact that when you run a 32-bit application on 64-bit Windows, it is actually a 64-bit process that executes 64-bit code on behalf of the 32-bit threads, and therefore there is a 64-bit thread stack and a 32-bit thread stack area reserved for each thread. The 64-bit stack has a reserve of 256K (except that on systems prior to Vista, the initial thread’s 64-bit stack is 1MB). Because every 32-bit thread begins its life in 64-bit mode and the stack space it uses when starting exceeds a page, you’ll typically see at least 16KB of the 64-bit stack committed. Here’s an example of a 32-bit thread’s 64-bit and 32-bit stacks (the one labeled “Wow64” is the 32-bit stack):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_5.png" width="554" height="112" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;32-bit Testlimit was able to create 3,204 threads on 64-bit Windows, which given that each thread uses 1MB+256K of address space for stack (again, except the first on versions of Windows prior to Vista, which uses 1MB+1MB), is exactly what you’d expect. I got different results when I ran 32-bit Testlimit on 64-bit Windows 7, however:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_6.png" width="554" height="135" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The difference between the Windows XP result and the Windows 7 result is caused by the more random nature of address space layout introduced in Windows Vista, Address Space Load Randomization (ASLR), that leads to some fragmentation. Randomization of DLL loading, thread stack and heap placement, helps defend against malware code injection. As you can see from this VMMap output, there’s 357MB of address space still available, but the largest free block is only 128K in size, which is smaller than the 1MB required for a 32-bit stack:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_16.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_7.png" width="244" height="163" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As I mentioned, a developer can override the default stack reserve. One reason to do so is to avoid wasting address space when a thread’s stack usage will always be significantly less than the default 1MB. Testlimit sets the default stack reservation in its PE image to 64K and when you include the –n switch along with the –t switch, Testlimit creates threads with 64K stacks.&amp;#160; Here’s the output on a 32-bit Windows XP system with 256MB RAM (I did this experiment on a small system to highlight this particular limit):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_18.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_8.png" width="554" height="112" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Note the different error, which implies that address space isn’t the issue here. In fact, 64K stacks should allow for around 32,000 threads (2GB/64K = 32,768). What’s the limit that’s being hit in this case? A look at the likely candidates, including commit and pool, don’t give any clues, as they’re all below their limits:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_20.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_9.png" width="374" height="247" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It’s only a look at additional memory information in the kernel debugger that reveals the threshold that’s being hit, resident available memory, which has been exhausted:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_26.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_12.png" width="483" height="185" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Resident available memory is the physical memory that can be assigned to data or code that must be kept in RAM. Nonpaged pool and nonpaged drivers count against it, for example, as does memory that’s locked in RAM for device I/O operations. Every thread has both a user-mode stack, which is what I’ve been talking about, but they also have a kernel-mode stack that’s used when they run in kernel mode, for example while executing system calls. When a thread is active its kernel stack is locked in memory so that the thread can execute code in the kernel that can’t page fault. &lt;/p&gt;  &lt;p&gt;A basic kernel stack is 12K on 32-bit Windows and 24K on 64-bit Windows. 14,225 threads require about 170MB of resident available memory, which corresponds to exactly how much is free on this system when Testlimit isn’t running:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_28.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_13.png" width="457" height="144" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once the resident available memory limit is hit, many basic operations begin failing. For example, here’s the error I got when I double-clicked on the desktop’s Internet Explorer shortcut:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_thumb_3.png" width="415" height="127" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As expected, when run on 64-bit Windows with 256MB of RAM, Testlimit is only able to create 6,600 threads – roughly half what it created on 32-bit Windows with 256MB RAM - before running out of resident available memory:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_30.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_14.png" width="554" height="112" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The reason I said “basic” kernel stack earlier is that a thread that executes graphics or windowing functions gets a “large” stack when it executes the first call that’s 20K on 32-bit Windows and 48K on 64-bit Windows. Testlimit’s threads don’t call any such APIs, so they have basic kernel stacks. &lt;/p&gt;  &lt;h3&gt;64-bit Thread Limits&lt;/h3&gt;  &lt;p&gt;Like 32-bit threads, 64-bit threads also have a default of 1MB reserved for stack, but 64-bit processes have a much larger user-mode address space (8TB), so address space shouldn’t be an issue when it comes to creating large numbers of threads. Resident available memory is obviously still a potential limiter, though. The 64-bit version of Testlimit (Testlimit64.exe) was able to create around 6,600 threads with and without the –n switch on the 256MB 64-bit Windows XP system, the same number that the 32-bit version created, because it also hit the resident available memory limit. However, on a system with 2GB of RAM, Testlimit64 was able to create only 55,000 threads, far below the number it should have been able to if resident available memory was the limiter (2GB/24K = 89,000):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_22.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_1.png" width="554" height="130" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this case, it’s the initial thread stack commit that causes the system to run out of virtual memory and the “paging file is too small” error. Once the commit level reached the size of RAM, the rate of thread creation slowed to a crawl because the system started thrashing, paging out stacks of threads created earlier to make room for the stacks of new threads, and the paging file had to expand. The results are the same when the –n switch is specified, because the threads have the same initial stack commitment. &lt;/p&gt;  &lt;h3&gt;Process Limits&lt;/h3&gt;  &lt;p&gt;The number of processes that Windows supports obviously must be less than the number of threads, since each process has one thread and a process itself causes additional resource usage. 32-bit Testlimit running on a 2GB 64-bit Windows XP system created about 8,400 processes:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_32.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_10.png" width="554" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;A look in the kernel debugger shows that it hit the resident available memory limit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_36.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_16.png" width="435" height="97" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If the only cost of a process with respect to resident available memory was the kernel-mode thread stack, Testlimit would have been able to create far more than 8,400 threads on a 2GB system. The amount of resident available memory on this system when Testlimit isn’t running is 1.9GB:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_38.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_17.png" width="361" height="45" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Dividing the amount of resident memory Testlimit used (1.9GB) by the number of processes it created (8,400) yields 230K of resident memory per process. Since a 64-bit kernel stack is 24K, that leaves about 206K unaccounted for. Where’s the rest of the cost coming from? When a process is created, Windows reserves enough physical memory to accommodate the process’s minimum working set size. This acts as a guarantee to the process that no matter what, there will enough physical memory available to hold enough data to satisfy its minimum working set. The default working set size happens to be 200KB, a fact that’s evident when you add the Minimum Working Set column to &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx"&gt;Process Explorer’s&lt;/a&gt; display:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_40.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_18.png" width="317" height="349" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The remaining roughly 6K is resident available memory charged for additional non-pageable memory allocated to represent a process. A process on 32-bit Windows will use slightly less resident memory because its kernel-mode thread stack is smaller. &lt;/p&gt;  &lt;p&gt;As they can for user-mode thread stacks, processes can override their default working set size with the &lt;a href="http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx"&gt;SetProcessWorkingSetSize&lt;/a&gt; function. Testlimit supports a –n switch, that when combined with –p, causes child processes of the main Testlimit process to set their working set to the minimum possible, which is 80K. Because the child processes must run to shrink their working sets, Testlimit sleeps after it can’t create any more processes and then tries again to give its children a chance to execute. Testlimit executed with the –n switch on a Windows 7 system with 4GB of RAM hit a limit other than resident available memory: the system commit limit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_24.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_11.png" width="554" height="373" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here you can see the kernel debugger reporting not only that the system commit limit had been hit, but that there have been thousands of memory allocation failures, both virtual and paged pool allocations, following the exhaustion of the commit limit (the system commit limit was actually hit several times as the paging file was filled and then grown to raise the limit):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_34.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_8FCD/image_thumb_15.png" width="463" height="205" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The baseline commitment before Testlimit ran was about 1.5GB, so the threads had consumed about 8GB of committed memory. Each process therefore consumed roughly 8GB/6,600, or 1.2MB. The output of the kernel debugger’s !vm command, which shows the private memory allocated by each active process, confirms that calculation:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsProcessandThrea_C851/image_thumb_2.png" width="383" height="342" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The initial thread stack commitment, described earlier, has a negligible impact with the rest coming from the memory required for the process address space data structures, page table entries, the handle table, process and thread objects, and private data the process creates when it initializes. &lt;/p&gt;  &lt;h3&gt;How Many Threads and Processes are Enough?&lt;/h3&gt;  &lt;p&gt;So the answer to the questions, “how many threads does Windows support?” and “how many processes can you run concurrently on Windows?” depends. In addition to the nuances of the way that the threads specify their stack sizes and processes specify their minimum working sets, the two major factors that determine the answer on any particular system include the amount of physical memory and the system commit limit. In any case, applications that create enough threads or processes to get anywhere near these limits should rethink their design, as there are almost always alternate ways to accomplish the same goals with a reasonable number. For instance, the general goal for a scalable application is to keep the number of threads running equal to the number of CPUs (with NUMA changing this to consider CPUs per node) and one way to achieve that is to switch from using synchronous I/O to using asynchronous I/O and rely on I/O completion ports to help match the number of running threads to the number of CPUs. &lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3261309" width="1" height="1"&gt;</description></item><item><title>Windows Internals 5th Edition is Available!</title><link>http://blogs.technet.com/markrussinovich/archive/2009/07/06/3261631.aspx</link><pubDate>Mon, 06 Jul 2009 13:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3261631</guid><dc:creator>markrussinovich</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3261631.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3261631</wfw:commentRss><description>&lt;p&gt;I’m proud to announce that Windows Internals, 5th Edition is now available. It’s been a long road, but a writing a book of this scope&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 0px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/WindowsInternals5thEditionReleased_5408/image_3.png" width="190" height="244" /&gt;&lt;/a&gt; is an incredibly detailed endeavor. This new edition covers Windows Vista and Windows Server 2008 (32-bit and 64-bit) and besides revisions and enhancements to existing content, adds an additional 250 pages, bringing the total page count to over 1200 (25% longer than the previous edition). Besides new experiments highlighting the Sysinternals tools, new topics covered include Hyper-V, the image loader, debugging infrastructure, Kernel Transaction Manager, Code Integrity, Thread Pools, Mandatory Integrity Controls, Windows Driver Framework, and Bitlocker, to name a few.&lt;/p&gt;  &lt;p&gt;We decided not to keep coverage of Windows XP and Windows Server 2003 because describing the commonalities and differences in certain areas where there have been significant changes across versions would have been complicated and confusing. However, 99% of the book applies directly to Windows 7 and Windows Server 2008 R2, so you can get a jump start while we work on the 6&lt;sup&gt;th&lt;/sup&gt; edition, which will add coverage of these new versions of Windows. We anticipate adding another 75-100 pages of content (and not making any significant changes to existing text) and are shooting to have the book completed by the end of the year.&lt;/p&gt;  &lt;p&gt;You can watch me and &lt;a href="http://solsem.com/"&gt;David Solomon&lt;/a&gt; talking about the book and our history of collaboration in &lt;a href="http://channel9.msdn.com/posts/Charles/Mark-Russinovich-and-David-Solomon-Windows-Internals-5-Released/"&gt;this Channel 9 interview&lt;/a&gt; we recorded a couple of weeks ago. David and I coauthored the previous two editions alone, but this time around we add a third contributor, &lt;a href="http://www.alex-ionescu.com/"&gt;Alex Ionescu&lt;/a&gt;. Alex came to our attention back when he was a primary contributor to the kernel of the ReactOS project, an attempt to develop an open source clone of Windows. Alex now teaches Windows internals training classes with David Solomon, including on campus here at Microsoft like I used to do before I joined Microsoft. Needless to say, Alex was a valuable addition to our team on this revision of the book.&lt;/p&gt;  &lt;p&gt;Be sure to visit the official &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;Windows Internals book page&lt;/a&gt;, where you can find more information on the book’s contents, errata (there is none at this point), and the downloads for the book’s demonstration programs like Testlimit, a tool that I’ve used in some of my &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963890.aspx"&gt;Pushing the Limits of Windows&lt;/a&gt; blog posts to highlight various resource limits in Windows. &lt;/p&gt;  &lt;p&gt;I have one more thing I want to share with you, &lt;a href="http://windowsteamblog.com/blogs/springboard/archive/2009/06/22/you-ve-angered-the-great-master-russinovich.aspx"&gt;a video&lt;/a&gt; that the Windows marketing team put together as part of the &lt;a href="http://talkingaboutwindows.com/"&gt;Talking About Windows&lt;/a&gt; campaign that has elementary school students Sam and Trevor talking about Sysinternals. I didn’t know about the video until they sent it to me, and I have to admit that besides being flattered, I laughed out loud. &lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3261631" width="1" height="1"&gt;</description></item><item><title>The Case of the Slow Keynote Demo</title><link>http://blogs.technet.com/markrussinovich/archive/2009/05/26/3244913.aspx</link><pubDate>Tue, 26 May 2009 09:30:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3244913</guid><dc:creator>markrussinovich</dc:creator><slash:comments>31</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3244913.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3244913</wfw:commentRss><description>&lt;P&gt;A couple of weeks ago I participated for the first time in the &lt;A href="http://www.msteched.com/online/view.aspx?tid=6fc7b7da-2d2d-4e57-9acf-cf77890a1738" mce_href="http://www.msteched.com/online/view.aspx?tid=6fc7b7da-2d2d-4e57-9acf-cf77890a1738"&gt;keynote at Microsoft’s Teched US conference&lt;/A&gt; to a room of over 5,000 attendees. Bill Veghte, the Senior Vice President of Windows marketing, led the keynote and gave a tour of the user-focused features of Windows 7, Iain McDonald, General Manager for Windows Server, demonstrated new functionality in Hyper-V and Windows Server 2008 R2, and I demonstrated IT Pro-oriented enhancements in Windows 7 and Microsoft Desktop Optimization Pack (MDOP).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I showed features like &lt;A href="http://www.microsoft.com/windows/enterprise/products/windows-7-bitlocker.aspx" mce_href="http://www.microsoft.com/windows/enterprise/products/windows-7-bitlocker.aspx"&gt;BitLocker To Go&lt;/A&gt; group policy settings, PowerShell v2’s remoting capabilities, PowerShell’s ability to script group policy objects, Microsoft Enterprise Desktop Virtualization (MEDV) and how the combination of App-V, roaming user profiles and folder redirection enable a replaceable PC scenario with minimal downtime. One point I reinforced was the fact that we made every effort to ensure that application-compatibility fixes (called shims) that IT Pros have developed for Vista applications work on Windows 7. I also demonstrated Windows 7’s new &lt;A href="http://www.microsoft.com/windows/enterprise/products/applocker.aspx" mce_href="http://www.microsoft.com/windows/enterprise/products/applocker.aspx"&gt;AppLocker&lt;/A&gt; feature, which allows IT Pros to restrict the software that users can run on enterprise desktops with flexible rules for identifying software. &lt;/P&gt;
&lt;P&gt;In the weeks leading up to the keynote I worked with Jason Leznek, the owner of the IT Pro portion of the keynote, to identify the features I’d showcase and to design the demos. We used dry runs to walk through the script, tweaking the demos and creating transitions, trimming content to fit the time allotted to my segment, and tightening my narration to focus on the benefits of the new technologies. For the application-compatibility demo, we decided to use a sample program used internally at Microsoft, called Stock Viewer, that’s intentionality incompatible with Vista and Windows 7 in ways representative of actual line-of-business software that doesn’t run without assistance on these newer operating systems. In my demo, I would launch Stock Viewer on Windows 7 and show how its trends report function fails with an obscure error message caused by incompatibility:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_28.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_28.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_13.png" width=553 height=320 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_13.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Then I’d show how I could deploy an application compatibility shim that enables the application to work correctly on Vista and then rerun the application successfully. &lt;/P&gt;
&lt;P&gt;We also wanted to show how AppLocker’s rule creation wizard makes it easy to allow software to run based on the publisher or version if the software is digitally signed. Originally, we planned on showing AppLocker after the application compatibility demo and enabling Adobe Acrobat Reader, an application commonly used in enterprises. We rehearsed this flow a couple of times, but found the transitions a little awkward, so I suggested that we sign the Stock Viewer executable and move the AppLocker demo before the shim demo. I’d be able to enable Stock Viewer to run with an AppLocker rule and then show how the shim helps it run correctly, using it for both demos. &lt;/P&gt;
&lt;P&gt;I went back to my office, signed Stock Viewer with the &lt;A href="http://technet.microsoft.com/en-us/sysinternals" mce_href="http://technet.microsoft.com/en-us/sysinternals"&gt;Sysinternals&lt;/A&gt; signing certificate and sent it to Jason. A few hours later he emailed me saying that something was wrong with the demo system because Stock Viewer, which had previously launched instantly, now took over a minute to start. We were counting down to TechEd and he was panicked because we needed to nail down the demos. I had heard at some point in the past that .NET does authenticode signature checks when it loads digitally signed assemblies, so my first suspicion was that it was related to that. I asked Jason to capture a &lt;A href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor&lt;/A&gt; trace and he emailed it back a few minutes later.&lt;/P&gt;
&lt;P&gt;After opening the log, the first thing I did was filter events for StockViewer.exe by finding its first operation and right-clicking to set a quick filter:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_6.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_6.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_2.png" width=358 height=226 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Then I looked at the timestamps on the first item, 2:27:20, and the last item, 2:28:32, which correlated with the minute delay Jason had observed. As I scrolled through the trace I saw many references to cryptography (crypto) Registry keys and file system directories, as well as references to TCP/IP settings, but I knew that there had to be at least one major gap in the timestamps to account for the long delay. I scanned the log from the beginning and found a gap of roughly 10 seconds at 2:27:22: &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_4.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_4.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_1.png" width=554 height=162 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The operations immediately before were references to the Rasadhlp.dll, a networking-related DLL, and a little earlier there were lots of references to Winsock registry keys, with accesses to crypto Registry keys immediately after the 10 second delay. It appeared that the system was not connected to the Internet and that the application was held up by some networking timeout of roughly 10 seconds. I looked forward in order to find the next gap and came across a 12-second interval:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_8.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_8.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_3.png" width=554 height=109 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_3.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Again, networking-related activity before, and crypto related activity after. The subsequent gap, also of 12-seconds, was identical:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_10.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_10.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_4.png" width=554 height=125 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_4.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;In fact, the next few gaps looked virtually identical. In each case there was a reference to HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections immediately before the pause, so I set a filter for that path and RegOpenKey and sure enough, could easily see six gaps of exactly 12-seconds each:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_18.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_18.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb.png" width=554 height=135 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The sum of the gaps – 12 times 6 – equaled the delay Jason was seeing. Next, I wanted to verify that the repeated attempts to access the network were caused by signing verification so I started looking at the stacks of various events by selecting them and typing Ctrl+K to open the stack properties dialog. The stack for events related to the Internet connection settings revealed that crypto was the reason: &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_25.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_25.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_8.png" width=411 height=230 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_8.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;One final piece of evidence I wanted to check for was that .NET was ultimately responsible for these checks. I rescanned the log and I saw events in the trace that confirmed that Stock Viewer is a .NET application:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_16.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_16.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_7.png" width=554 height=103 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_7.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I also looked at the stacks of some of the early events referencing crypto Registry keys and saw that it was the .NET runtime performing the call to &lt;A href="http://msdn.microsoft.com/en-us/library/aa388208.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa388208.aspx"&gt;WinVerifyTrust&lt;/A&gt;, the Windows function for checking the digital signature on a file, that started the cascade of attempted Internet accesses:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_24.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_24.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_11.png" width=476 height=299 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_11.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Confident now that the cause of the startup delay was due to .NET seeing that Stockviewer.exe was signed and then checking to see if the signing certificate had been revoked, I entered Web searches looking for a way to make .NET to skip the check, since I knew that the keynote machines probably wouldn’t be connected to the Internet during the actual keynote. After a couple of minutes of reading through articles by others with similar experiences, I found this &lt;A href="http://support.microsoft.com/kb/936707" mce_href="http://support.microsoft.com/kb/936707"&gt;KB article&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_20.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_20.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_9.png" width=554 height=206 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowKeynoteDemo_7894/image_thumb_9.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The article describes exactly the symptoms we were seeing and notes that .NET 2.0, which is the version of .NET I could see Stock Viewer was using based on the paths of the .NET DLLs it accessed during the trace, supports a way to turn off its obligatory checking of assembly digital signatures: create a configuration file in the executable’s directory with the same name as the executable except with “.config” appended (e.g. StockViewer.exe.config) containing the following XML:&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;lt;configuration&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;runtime&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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;lt;generatePublisherEvidence enabled="false"/&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/runtime&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;lt;/configuration&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;A total of about 15 minutes since I had received Jason’s email, I sent him a reply explaining my conclusion with the configuration file attached. Shortly after, he wrote back confirming the delays were gone and expressing amazement that I had figured out the problem and solution so quickly. It might have seemed like magic to him, but I had simply used basic Process Monitor troubleshooting techniques and the Web to solve the case. Needless to say, the revised demo flow and transition between AppLocker and application compatibility came off great. &lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3244913" width="1" height="1"&gt;</description></item><item><title>Pushing the Limits of Windows: Paged and Nonpaged Pool</title><link>http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx</link><pubDate>Thu, 26 Mar 2009 18:02:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3211216</guid><dc:creator>markrussinovich</dc:creator><slash:comments>35</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3211216.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3211216</wfw:commentRss><description>&lt;p&gt;In previous Pushing the Limits posts, I described the two most basic system resources, &lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx"&gt;physical memory&lt;/a&gt; and &lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx"&gt;virtual memory&lt;/a&gt;. This time I’m going to describe two fundamental kernel resources, paged pool and nonpaged pool, that are based on those, and that are directly responsible for many other system resource limits including the maximum number of processes, synchronization objects, and handles. The subsequent posts in this series are:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx"&gt;Pushing the Limits of Windows: Processes and Threads&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/09/29/3283844.aspx"&gt;Pushing the Limits of Windows: Handles&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Paged and nonpaged pools serve as the memory resources that the operating system and device drivers use to store their data structures. The pool manager operates in kernel mode, using regions of the system’s virtual address space (described in the Pushing the Limits post on virtual memory) for the memory it sub-allocates. The kernel’s pool manager operates similarly to the C-runtime and Windows heap managers that execute within user-mode processes.&amp;#160; Because the minimum virtual memory allocation size is a multiple of the system page size (4KB on x86 and x64), these subsidiary memory managers carve up larger allocations into smaller ones so that memory isn’t wasted. &lt;/p&gt;  &lt;p&gt;For example, if an application wants a 512-byte buffer to store some data, a heap manager takes one of the regions it has allocated and notes that the first 512-bytes are in use, returning a pointer to that memory and putting the remaining memory on a list it uses to track free heap regions. The heap manager satisfies subsequent allocations using memory from the free region, which begins just past the 512-byte region that is allocated. &lt;/p&gt;  &lt;h3&gt;Nonpaged Pool&lt;/h3&gt;  &lt;p&gt;The kernel and device drivers use nonpaged pool to store data that might be accessed when the system can’t handle page faults. The kernel enters such a state when it executes interrupt service routines (ISRs) and deferred procedure calls (DPCs), which are functions related to hardware interrupts. Page faults are also illegal when the kernel or a device driver acquires a spin lock, which, because they are the only type of lock that can be used within ISRs and DPCs, must be used to protect data structures that are accessed from within ISRs or DPCs and either other ISRs or DPCs or code executing on kernel threads. Failure by a driver to honor these rules results in the most common crash code, &lt;a href="http://msdn.microsoft.com/en-us/library/ms793589.aspx"&gt;IRQL_NOT_LESS_OR_EQUAL&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Nonpaged pool is therefore always kept present in physical memory and nonpaged pool virtual memory is assigned physical memory. Common system data structures stored in nonpaged pool include the kernel and objects that represent processes and threads, synchronization objects like mutexes, semaphores and events, references to files, which are represented as file objects, and I/O request packets (IRPs), which represent I/O operations. &lt;/p&gt;  &lt;h3&gt;Paged Pool&lt;/h3&gt;  &lt;p&gt;Paged pool, on the other hand, gets its name from the fact that Windows can write the data it stores to the paging file, allowing the physical memory it occupies to be repurposed. Just as for user-mode virtual memory, when a driver or the system references paged pool memory that’s in the paging file, an operation called a page fault occurs, and the memory manager reads the data back into physical memory. The largest consumer of paged pool, at least on Windows Vista and later, is typically the Registry, since references to registry keys and other registry data structures are stored in paged pool. The data structures that represent memory mapped files, called &lt;em&gt;sections &lt;/em&gt;internally, are also stored in paged pool. &lt;/p&gt;  &lt;p&gt;Device drivers use the &lt;a href="http://msdn.microsoft.com/en-us/library/ms796989.aspx"&gt;ExAllocatePoolWithTag&lt;/a&gt; API to allocate nonpaged and paged pool, specifying the type of pool desired as one of the parameters. Another parameter is a 4-byte &lt;em&gt;Tag&lt;/em&gt;, which drivers are supposed to use to uniquely identify the memory they allocate, and that can be a useful key for tracking down drivers that leak pool, as I’ll show later. &lt;/p&gt;  &lt;h3&gt;Viewing Paged and Nonpaged Pool Usage&lt;/h3&gt;  &lt;p&gt;There are three performance counters that indicate pool usage:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Pool nonpaged bytes &lt;/li&gt;    &lt;li&gt;Pool paged bytes (virtual size of paged pool – some may be paged out) &lt;/li&gt;    &lt;li&gt;Pool paged resident bytes (physical size of paged pool) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;However, there are no performance counters for the maximum size of these pools. They can be viewed with the kernel debugger !vm command, but with Windows Vista and later to use the kernel debugger in local kernel debugging mode you must boot the system in debugging mode, which disables MPEG2 playback. &lt;/p&gt;  &lt;p&gt;So instead, use Process Explorer to view both the currently allocated pool sizes, as well as the maximum. To see the maximum, you’ll need to configure Process Explorer to use symbol files for the operating system. First, install the latest &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;Debugging Tools for Windows&lt;/a&gt; package. Then run Process Explorer and open the Symbol Configuration dialog in the Options menu and point it at the dbghelp.dll in the Debugging Tools for Windows installation directory and set the symbol path to point at Microsoft’s symbol server:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_1.png" width="404" height="221" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After you’ve configured symbols, open the System Information dialog (click System Information in the View menu or press Ctrl+I) to see the pool information in the Kernel Memory section. Here’s what that looks like on a 2GB Windows XP system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_2.png" width="184" height="123" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; 2GB 32-bit Windows XP&lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Nonpaged Pool Limits&lt;/h3&gt;  &lt;p&gt;As I mentioned in a previous post, on 32-bit Windows, the system address space is 2GB by default. That inherently caps the upper bound for nonpaged pool (or any type of system virtual memory) at 2GB, but it has to share that space with other types of resources such as the kernel itself, device drivers, system Page Table Entries (PTEs), and cached file views. &lt;/p&gt;  &lt;p&gt;Prior to Vista, the memory manager on 32-bit Windows calculates how much address space to assign each type at boot time. Its formulas takes into account various factors, the main one being the amount of physical memory on the system.&amp;#160; The amount it assigns to nonpaged pool starts at 128MB on a system with 512MB and goes up to 256MB for a system with a little over 1GB or more. On a system booted with the /3GB option, which expands the user-mode address space to 3GB at the expense of the kernel address space, the maximum nonpaged pool is 128MB. The Process Explorer screenshot shown earlier reports the 256MB maximum on a 2GB Windows XP system booted without the /3GB switch. &lt;/p&gt;  &lt;p&gt;The memory manager in 32-bit Windows Vista and later, including Server 2008 and Windows 7 (there is no 32-bit version of Windows Server 2008 R2) doesn’t carve up the system address statically; instead, it dynamically assigns ranges to different types of memory according to changing demands. However, it still sets a maximum for nonpaged pool that’s based on the amount of physical memory, either slightly more than 75% of physical memory or 2GB, whichever is smaller. Here’s the maximum on a 2GB Windows Server 2008 system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_3.png" width="179" height="119" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; 2GB 32-bit Windows Server 2008&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;64-bit Windows systems have a much larger address space, so the memory manager can carve it up statically without worrying that different types might not have enough space. 64-bit Windows XP and Windows Server 2003 set the maximum nonpaged pool to a little over 400K per MB of RAM or 128GB, whichever is smaller. Here’s a screenshot from a 2GB 64-bit Windows XP system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_4.png" width="179" height="117" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;2GB 64-bit Windows XP&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;64-bit Windows Vista, Windows Server 2008, Windows 7 and Windows Server 2008 R2 memory managers match their 32-bit counterparts (where applicable – as mentioned earlier, there is no 32-bit version of Windows Server 2008 R2) by setting the maximum to approximately 75% of RAM, but they cap the maximum at 128GB instead of 2GB. Here’s the screenshot from a 2GB 64-bit Windows Vista system, which has a nonpaged pool limit similar to that of the 32-bit Windows Server 2008 system shown earlier. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_5.png" width="176" height="121" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;2GB 32-bit Windows Server 2008 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Finally, here’s the limit on an 8GB 64-bit Windows 7 system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_24.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_10.png" width="176" height="118" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;8GB 64-bit Windows 7&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Here’s a table summarizing the nonpaged pool limits across different version of Windows:&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="636"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="219"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="208" align="center"&gt;&lt;strong&gt;32-bit&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="207" align="center"&gt;&lt;strong&gt;64-bit&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="218"&gt;&lt;strong&gt;XP, Server 2003&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="208" align="center"&gt;up to 1.2GB RAM: 32-256 MB&amp;#160; &lt;br /&gt;&amp;gt; 1.2GB RAM: 256MB&lt;/td&gt;        &lt;td valign="top" width="207" align="center"&gt;min( ~400K/MB of RAM, 128GB)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="218"&gt;&lt;strong&gt;Vista, Server 2008,            &lt;br /&gt;Windows 7, Server 2008 R2&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="208" align="center"&gt;min( ~75% of RAM, 2GB)&lt;/td&gt;        &lt;td valign="top" width="208" align="center"&gt;min(~75% of RAM, 128GB)&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;h3&gt;Paged Pool Limits&lt;/h3&gt;  &lt;p&gt;The kernel and device drivers use paged pool to store any data structures that won’t ever be accessed from inside a DPC or ISR or when a spinlock is held. That’s because the contents of paged pool can either be present in physical memory or, if the memory manager’s working set algorithms decide to repurpose the physical memory, be sent to the paging file and demand-faulted back into physical memory when referenced again. Paged pool limits are therefore primarily dictated by the amount of system address space the memory manager assigns to paged pool, as well as the system commit limit. &lt;/p&gt;  &lt;p&gt;On 32-bit Windows XP, the limit is calculated based on how much address space is assigned other resources, most notably system PTEs, with an upper limit of 491MB. The 2GB Windows XP System shown earlier has a limit of 360MB, for example:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_2.png" width="184" height="123" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; &lt;em&gt;2GB 32-bit Windows XP&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;32-bit Windows Server 2003 reserves more space for paged pool, so its upper limit is 650MB. &lt;/p&gt;  &lt;p&gt;Since 32-bit Windows Vista and later have dynamic kernel address space, they simply set the limit to 2GB. Paged pool will therefore run out either when the system address space is full or the system commit limit is reached. &lt;/p&gt;  &lt;p&gt;64-bit Windows XP and Windows Server 2003 set their maximums to four times the nonpaged pool limit or 128GB, whichever is smaller. Here again is the screenshot from the 64-bit Windows XP system, which shows that the paged pool limit is exactly four times that of nonpaged pool:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_4.png" width="179" height="117" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2GB 64-bit Windows XP&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Finally, 64-bit versions of Windows Vista, Windows Server 2008, Windows 7 and Windows Server 2008 R2 simply set the maximum to 128GB, allowing paged pool’s limit to track the system commit limit. Here’s the screenshot of the 64-bit Windows 7 system again:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_24.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_10.png" width="176" height="118" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; 8GB 64-bit Windows 7&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Here’s a summary of paged pool limits across operating systems:&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="696"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="215"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="227" align="center"&gt;&lt;strong&gt;32-bit&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="252" align="center"&gt;&lt;strong&gt;64-bit&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="215"&gt;&lt;strong&gt;XP, Server 2003&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="227" align="center"&gt;XP: up to 491MB          &lt;br /&gt;Server 2003: up to 650MB&lt;/td&gt;        &lt;td valign="top" width="252" align="center"&gt;min( 4 * nonpaged pool limit, 128GB)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="215"&gt;&lt;strong&gt;Vista, Server 2008,            &lt;br /&gt;Windows 7, Server 2008 R2&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="227" align="center"&gt;min( system commit limit, 2GB)&lt;/td&gt;        &lt;td valign="top" width="252" align="center"&gt;min( system commit limit, 128GB)&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;h3&gt;Testing Pool Limits&lt;/h3&gt;  &lt;p&gt;Because the kernel pools are used by almost every kernel operation, exhausting them can lead to unpredictable results. If you want to witness first hand how a system behaves when pool runs low, use the &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;Notmyfault&lt;/a&gt; tool. It has options that cause it to leak either nonpaged or paged pool in the increment that you specify. You can change the leak size while it’s leaking if you want to change the rate of the leak and Notmyfault frees all the leaked memory when you exit it:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb.png" width="251" height="450" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Don’t run this on a system unless you’re prepared for possible data loss, as applications and I/O operations will start failing when pool runs out. You might even get a blue screen if the driver doesn’t handle the out-of-memory condition correctly (which is considered a bug in the driver). The Windows Hardware Quality Laboratory (WHQL) stresses drivers using the Driver Verifier, a tool built into Windows, to make sure that they can tolerate out-of-pool conditions without crashing, but you might have third-party drivers that haven’t gone through such testing or that have bugs that weren’t caught during WHQL testing. &lt;/p&gt;  &lt;p&gt;I ran Notmyfault on a variety of test systems in virtual machines to see how they behaved and didn’t encounter any system crashes, but did see erratic behavior. After nonpaged pool ran out on a 64-bit Windows XP system, for example, trying to launch a command prompt resulted in this dialog:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_16.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_6.png" width="420" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On a 32-bit Windows Server 2008 system where I already had a command prompt running, even simple operations like changing the current directory and directory listings started to fail after nonpaged pool was exhausted:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_18.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_7.png" width="554" height="102" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On one test system, I eventually saw this error message indicating that data had potentially been lost. I hope you never see this dialog on a real system!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_42.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_19.png" width="554" height="108" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Running out of paged pool causes similar errors. Here’s the result of trying to launch Notepad from a command prompt on a 32-bit Windows XP system after paged pool had run out. Note how Windows failed to redraw the window’s title bar and the different errors encountered for each attempt:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_20.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_8.png" width="444" height="131" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And here’s the start menu’s Accessories folder failing to populate on a 64-bit Windows Server 2008 system that’s out of paged pool:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_22.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_9.png" width="181" height="59" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here you can see the system commit level, also displayed on Process Explorer’s System Information dialog, quickly rise as Notmyfault leaks large chunks of paged pool and hits the 2GB maximum on a 2GB 32-bit Windows Server 2008 system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_26.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_11.png" width="202" height="84" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The reason that Windows doesn’t simply crash when pool is exhausted, even though the system is unusable, is that pool exhaustion can be a temporary condition caused by an extreme workload peak, after which pool is freed and the system returns to normal operation. When a driver (or the kernel) leaks pool, however, the condition is permanent and identifying the cause of the leak becomes important. That’s where the pool tags described at the beginning of the post come into play.&lt;/p&gt;  &lt;h3&gt;Tracking Pool Leaks&lt;/h3&gt;  &lt;p&gt;When you suspect a pool leak and the system is still able to launch additional applications, Poolmon, a tool in the &lt;a href="http://www.microsoft.com/whdc/devtools/WDK/"&gt;Windows Driver Kit&lt;/a&gt;, shows you the number of allocations and outstanding bytes of allocation by type of pool and the tag passed into calls of ExAllocatePoolWithTag. Various hotkeys cause Poolmon to sort by different columns; to find the leaking allocation type, use either ‘b’ to sort by bytes or ‘d’ to sort by the difference between the number of allocations and frees. Here’s Poolmon running on a system where Notmyfault has leaked 14 allocations of about 100MB each:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_38.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_17.png" width="554" height="192" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After identifying the guilty tag in the left column, in this case ‘Leak’, the next step is finding the driver that’s using it. Since the tags are stored in the driver image, you can do that by scanning driver images for the tag in question. The &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx"&gt;Strings&lt;/a&gt; utility from Sysinternals dumps printable strings in the files you specify (that are by default a minimum of three characters in length), and since most device driver images are in the %Systemroot%\System32\Drivers directory, you can open a command prompt, change to that directory and execute “strings * | findstr &amp;lt;tag&amp;gt;”. After you’ve found a match, you can dump the driver’s version information with the Sysinternals &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897441.aspx"&gt;Sigcheck&lt;/a&gt; utility. Here’s what that process looks like when looking for the driver using “Leak”:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_30.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_13.png" width="444" height="263" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If a system has crashed and you suspect that it’s due to pool exhaustion, load the crash dump file into the Windbg debugger, which is included in the Debugging Tools for Windows package, and use the !vm command to confirm it. Here’s the output of !vm on a system where Notmyfault has exhausted nonpaged pool:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_34.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_15.png" width="434" height="221" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once you’ve confirmed a leak, use the !poolused command to get a view of pool usage by tag that’s similar to Poolmon’s. !poolused by default shows unsorted summary information, so specify 1 as the the option to sort by paged pool usage and 2 to sort by nonpaged pool usage:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_36.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsPool_9AFB/image_thumb_16.png" width="344" height="142" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Use Strings on the system where the dump came from to search for the driver using the tag that you find causing the problem. &lt;/p&gt;  &lt;p&gt;So far in this blog series I’ve covered the most fundamental limits in Windows, including physical memory, virtual memory, paged and nonpaged pool. Next time I’ll talk about the limits for the number of processes and threads that Windows supports, which are limits that derive from these.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3211216" width="1" height="1"&gt;</description></item><item><title>The Case of the Phantom Desktop Files</title><link>http://blogs.technet.com/markrussinovich/archive/2009/02/03/3174194.aspx</link><pubDate>Tue, 03 Feb 2009 09:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3174194</guid><dc:creator>markrussinovich</dc:creator><slash:comments>70</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3174194.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3174194</wfw:commentRss><description>&lt;p&gt;A few weeks ago, my wife mentioned that she sometimes saw files in her desktop folder that didn’t appear on the actual desktop. She brought it up not only because she was confused by the discrepancy, but because she wanted to move some of these phantom files to other folders and wanted to delete others. I had no idea what she was talking about (which was usually the case when she described her computer troubles), so I told her that the next time she saw these mysterious files, to call me to look at it. &lt;/p&gt;  &lt;p&gt;A few days later I got home from work and she greeted me excitedly at the door and explained that the problem reoccurred and that she had left a window open showing the elusive files. I rushed to the kitchen computer with anticipation, not even bothering to greet the dogs on the way, and surveyed the situation. She had a maximized IE window open with a full row of tabs for her open emails (I don’t think she ever closes an email window). An IE “Choose a File” dialog box was in the foreground listing the files in her desktop folder, which she had opened by clicking the attachment button in the email editor. The dialog looked like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_4.png" width="420" height="245" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I minimized IE to view the desktop background and sure enough, several of the files visible in the dialog, such as the “Maui Feb. 08” folder and the CIMG13xx JPG files, were missing. I opened an Explorer window and navigated to her desktop folder to see if the files would show up there, but they were missing there as well:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_2.png" width="422" height="265" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I’d never seen that behavior before. I knew this was a job for &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor&lt;/a&gt;. Since my wife doesn’t keep the Sysinternals tools on her system (sad, but true), I ran it directly from the network using the Sysinternals Live address, &lt;a href="file://\\live.sysinternals.com\tools\procmon.exe"&gt;\\live.sysinternals.com\tools\procmon.exe&lt;/a&gt;. With Process Monitor recording activity, I closed and reopened the Choose File dialog from the email editor and then I search for “CIMG”, a portion of the file name for many of the files present in the Choose File dialog, but not in the Explorer view of the desktop. The first hit was a directory enumeration operation with the file names showing as results in the Details column on the far right:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_26.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_12.png" width="554" height="72" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The files were located in her profile under \Appdata\Local\Microsoft\Windows\Temporary Internet Files\Virtualized\C\Users\Daryl\Desktop. This Virtualized is directory created by IE7 when run in Protected Mode (PMIE), which is the default mode on Windows Vista and Windows Server 2008.&lt;/p&gt;  &lt;p&gt;PMIE uses Integrity Levels, introduced in Vista and Server 2008, to limit the file system and registry locations to which code running in IE can modify to a subset of those writeable by the user account in which IE executes. As I described in an &lt;a href="http://blogs.technet.com/markrussinovich/archive/2007/02/12/638372.aspx "&gt;earlier blog post&lt;/a&gt;, the sandbox defined by locations labeled with Low Integrity, the level at which PMIE executes and of the objects that PMIE can modify, allow PMIE to save favorites and temporary files, like the IE cache and browsing history. However, PMIE cannot modify other locations in a user’s account, like documents folders and per-user autostart locations in the registry and file system, because they have an integrity level of Medium. That prevents drive-by-download malware that might infect the IE process from establishing a persistent presence. &lt;/p&gt;  &lt;p&gt;In order to preserve backward compatibility with legacy code, such as ActiveX controls and Browser Helper Objects, that might be coded to write to locations outside of the sandbox, PMIE implements &lt;em&gt;shims&lt;/em&gt; that intercepts file and registry operations and redirects ones that got outside the sandbox to the Virtualized directory within it.&lt;/p&gt;  &lt;p&gt;To see if that was what was happening here, I examined the stack trace of the virtualized operation highlighted above by right-clicking on the line and choosing Stack. The stack showed that Acredir.dll was intercepting the operation and executing redirection functions:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_22.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_10.png" width="391" height="198" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Double-clicking on the line in the stack trace opens the module properties dialog, which shows that the DLL is the “Windows Compatibility DLL”, thus confirming this was part of PMIE’s sandbox implementation:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_28.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_13.png" width="244" height="140" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I had been familiar with PMIE’s virtualization, but I’d never seen files virtualized on the desktop, so it had not been obvious to me that was what was causing the discrepancy. Process Monitor revealed the cause, so now all I was left with was cleaning up the virtualized files. Most users don’t realize that you can move and delete files from within a file browse dialog, so I took the opportunity to show my wife how she can manage virtualized files from the email editor’s attachment dialog if she came across them again. We deleted the files she didn’t want and moved the pictures out to her photo library folders. &lt;/p&gt;  &lt;p&gt;The case was closed. As a bonus, my wife was impressed at the ease with which I’d figured out the source of the phantom files and even more impressed that I wrote the tool I used to solve it. She’d also gotten an in depth look at PMIE’s virtualization and integrity levels, but I think in the end my lecturing on those subjects actually subtracted points. &lt;/p&gt;  &lt;p&gt;Incidentally, you’ll almost certainly see files and directories if you look at the PMIE Virtualized folder in your profile, because even routine operations within IE result in redirection. Here you can see thumbnail cache files that the shell’s file browsing dialog creates when you use it from within IE. Normally, the shell stores thumbnail cache files in your profile, but PMIE can’t write to that location so the shim virtualizes it:&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_20.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseofthePhantomDesktopFiles_4A85/image_thumb_9.png" width="443" height="246" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3174194" width="1" height="1"&gt;</description></item><item><title>The Case of the Crashed Phone Call</title><link>http://blogs.technet.com/markrussinovich/archive/2008/12/30/3174871.aspx</link><pubDate>Wed, 31 Dec 2008 01:42:03 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3174871</guid><dc:creator>markrussinovich</dc:creator><slash:comments>52</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3174871.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3174871</wfw:commentRss><description>&lt;p&gt;&lt;a href="http://www.solsem.com"&gt;David Solomon&lt;/a&gt;, my coauthor for the &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;Windows Internals&lt;/a&gt; books, was recently in the middle of an important VOIP call on Skype when the audio suddenly garbled. A second later the system blue screened. He called back after the reboot, but a half hour later the person on the other seemed to stop talking mid-word and the system crashed again. The conversation was essentially over anyway, and since he’d explained the first drop, Dave decided not to call back and formally end the call, but to investigate the cause of the crashes. He launched Windbg from the &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;Debugging Tools for Windows&lt;/a&gt; package, selected Open Crash Dump from the File menu, and chose %Systemroot%\Memory.dmp. &lt;/p&gt;  &lt;p&gt;He’d previously configured Windbg to use the Microsoft public symbol server by entering “srv*c:\symbols*http://msdl.microsoft.com/download/symbols” in the Windbg symbols configuration dialog, so Windbg knew how to interpret the crash dump file.&amp;#160; When Windbg loads a crash dump file, it automatically executes a heuristics-based analysis engine that identifies the driver or system component most likely responsible for the crash. The analysis output pointed at the NETw4v64.sys device driver:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_1.png" width="554" height="159" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;When you click on the “!analyze –v” hyperlink in the output, Windbg prints out some of the data it uses in its analysis. The analysis heuristics aren’t perfect, so Dave always clicks the link to look at the additional data, specifically the stack trace at the time of the crash and possibly memory locations associated with the crash. The stack trace records the nesting of function calls on the processor from which the kernel’s crash function, &lt;a href="http://msdn.microsoft.com/en-us/library/ms801645.aspx"&gt;KeBugCheckEx&lt;/a&gt;, was called. In this case the stack looked like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_5.png" width="254" height="89" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You read the stack from bottom to top to follow the chronology of function calls. The trace shows that some code in NETw4v64 called the kernel’s (“nt”) &lt;a href="http://msdn.microsoft.com/en-us/library/ms801950.aspx"&gt;KeAcquireSpinLockRaiseToDpc&lt;/a&gt; function. NETw4v64’s stack frame doesn’t have a text function name, which is expected for drivers that aren’t part of Windows and therefore don’t have symbols on the Microsoft symbol server. The next higher frame indicates that KeAcquireSpinLockRaiseToDpc called KiPageFault, most likely not directly, but as the result of a reference to a virtual memory address that wasn’t currently resident in physical memory. KiPageFault then called KeBugCheckEx with stop code A, which the extended analysis output describes as IRQL_NOT_LESS_OR_EQUAL:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_3.png" width="554" height="145" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Dave hypothesized that the NETw4v64 driver had called the kernel with a corrupted pointer that triggered the invalid memory reference. This particular crash might have been the result of random corruption, even by another driver, so he looked in the %Systemroot%\Minidump directory for the dump file for the first crash. On Windows Vista, the operating system he was running, the system always saves a kernel-memory dump to %Systemroot%\Memory.dmp, overwriting the previous dump, and archives an abbreviated form of the dump, called a minidump, to %Systemroot%\Minidump. He followed the same steps for the second dump and the analysis engine reported the exact same cause for the crash, down to the same corrupted memory pointer value.&lt;/p&gt;  &lt;p&gt;Without performing a meticulous manual analysis of a dump, you can’t be certain that the driver the heuristics point at is the culprit, but the first rule of crash mitigation is to make sure you have the latest versions of any implicated drivers. Sometimes Windows Update has optional updates that don’t apply automatically, so Dave went to the %Systemroot%\System32\drivers directory to investigate the NETw4v64.sys file for clues as to what device it was for. The file properties dialog showed that it was version 11.5 of the “Intel Wireless WiFi Link Driver”:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_6.png" width="381" height="281" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Armed with the knowledge that it was an Intel wireless network driver, he opened Device Manager, expanded the Network Adapters node and found a device with a similar name:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_16.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_7.png" width="310" height="98" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;He right-clicked and chose “Update Driver Software…” from the context menu to launch the driver update wizard, and told it to check Windows Update for a newer version. Unfortunately, it reported that he had the most current version installed:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_18.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_8.png" width="466" height="236" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Sometimes OEMs have drivers posted on their Web sites that they haven’t yet been made available to Windows Update, so Dave next went to Dell, the brand of his laptop, to check the version there. Again, the version he found posted seemed to match the one he had:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_22.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb_10.png" width="486" height="334" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;OEMs often get hardware vendors to create custom versions of hardware tuned for specific cost, power, capability or size requirements. The original hardware vendor will therefore not post drivers for an OEM-only device or post drivers that are generic and might not take advantage of OEM-specific features.&amp;#160; It’s always worth checking, though, so Dave went to Intel’s site. To his chagrin, not only was there a newer version that installed and worked as expected, but the Intel driver was version 12.1, a major release number higher than the one Dell was hosting:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_9.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheInterruptedPhoneCall_B31B/image_thumb.png" width="554" height="300" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Intel also conveniently offered the driver in a “Drivers-Only” download that was a mere 7MB, one tenth the size of the package on Dell’s site that also includes value-add management software.&amp;#160; &lt;/p&gt;  &lt;p&gt;Dave couldn’t conclusively close the case because he couldn’t be sure that the Intel driver was the actual cause of the crashes, but the crashes haven’t reoccurred. Even if the Intel driver wasn’t the root cause, Dave was happy that he picked up a newer version that most likely had performance, reliability and maybe even power-management improvements. The case is a great example of simple dump analysis and the lesson that Windows Update and even an OEM’s site might not have the most up-to-date drivers. Hopefully, Dell will start leveraging Windows Update to provide its customers the latest drivers.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3174871" width="1" height="1"&gt;</description></item><item><title>Pushing the Limits of Windows: Virtual Memory</title><link>http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx</link><pubDate>Mon, 17 Nov 2008 20:41:25 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3155406</guid><dc:creator>markrussinovich</dc:creator><slash:comments>83</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3155406.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3155406</wfw:commentRss><description>&lt;p&gt;In my &lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx"&gt;first Pushing the Limits of Windows post&lt;/a&gt;, I discussed physical memory limits, including the limits imposed by licensing, implementation, and driver compatibility. This time I’m turning my attention to another fundamental resource, virtual memory. Virtual memory separates a program’s view of memory from the system’s physical memory, so an operating system decides when and if to store the program’s code and data in physical memory and when to store it in a file. The major advantage of virtual memory is that it allows more processes to execute concurrently than might otherwise fit in physical memory.&lt;/p&gt;  &lt;p&gt;While virtual memory has limits that are related to physical memory limits, virtual memory has limits that derive from different sources and that are different depending on the consumer. For example, there are virtual memory limits that apply to individual processes that run applications, the operating system, and for the system as a whole. It's important to remember as you read this that virtual memory, as the name implies, has no direct connection with physical memory. Windows assigning the file cache a certain amount of virtual memory does not dictate how much file data it actually caches in physical memory; it can be any amount from none to more than the amount that's addressable via virtual memory. &lt;/p&gt;  &lt;h3&gt;Process Address Spaces&lt;/h3&gt;  &lt;p&gt;Each process has its own virtual memory, called an address space, into which it maps the code that it executes and the data that the code references and manipulates. A 32-bit process uses 32-bit virtual memory address pointers, which creates an absolute upper limit of 4GB (2^32) for the amount of virtual memory that a 32-bit process can address. However, so that the operating system can reference its own code and data and the code and data of the currently-executing process without changing address spaces, the operating system makes its virtual memory visible in the address space of every process. By default, 32-bit versions of Windows split the process address space evenly between the system and the active process, creating a limit of 2GB for each:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_28.png"&gt;&lt;img border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_12.png" width="93" height="200" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Applications might use Heap APIs, the .NET garbage collector, or the C runtime malloc library to allocate virtual memory, but under the hood all of these rely on the &lt;a href="http://msdn.microsoft.com/en-us/library/aa366887.aspx"&gt;VirtualAlloc&lt;/a&gt; API. When an application runs out of address space then VirtualAlloc, and therefore the memory managers layered on top of it, return errors (represented by a NULL address). The Testlimit utility, which I wrote for the &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;4th Edition of Windows Internals&lt;/a&gt; to demonstrate various Windows limits,&amp;#160; calls VirtualAlloc repeatedly until it gets an error when you specify the –r switch. Thus, when you run the 32-bit version of Testlimit on 32-bit Windows, it will consume the entire 2GB of its address space:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_20.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_9.png" width="471" height="129" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;2010 MB isn’t quite 2GB, but Testlimit’s other code and data, including its executable and system DLLs, account for the difference. You can see the total amount of address space it’s consumed by looking at its Virtual Size in &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx"&gt;Process Explorer&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_4.png" width="345" height="50" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Some applications, like SQL Server and Active Directory, manage large data structures and perform better the more that they can load into their address space at the same time. Windows NT 4 SP3 therefore introduced a boot option, &lt;a href="http://msdn.microsoft.com/en-us/library/ms791558.aspx"&gt;/3GB&lt;/a&gt;, that gives a process 3GB of its 4GB address space by reducing the size of the system address space to 1GB, and Windows XP and Windows Server 2003 introduced the /userva option that moves the split anywhere between 2GB and 3GB:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_30.png"&gt;&lt;img border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_13.png" width="93" height="200" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;To take advantage of the address space above the 2GB line, however, a process must have the ‘large address space aware’ flag set in its executable image. Access to the additional virtual memory is opt-in because some applications have assumed that they’d be given at most 2GB of the address space. Since the high bit of a pointer referencing an address below 2GB is always zero, they would use the high bit in their pointers as a flag for their own data, clearing it of course before referencing the data. If they ran with a 3GB address space they would inadvertently truncate pointers that have values greater than 2GB, causing program errors including possible data corruption. &lt;/p&gt;  &lt;p&gt;All Microsoft server products and data intensive executables in Windows are marked with the large address space awareness flag, including Chkdsk.exe, Lsass.exe (which hosts Active Directory services on a domain controller), Smss.exe (the session manager), and Esentutl.exe (the Active Directory Jet database repair tool). You can see whether an image has the flag with the Dumpbin utility, which comes with Visual Studio:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_10.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_4.png" width="554" height="325" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Testlimit is also marked large-address aware, so if you run it with the –r switch when booted with the 3GB of user address space, you’ll see something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_6.png" width="469" height="126" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Because the address space on 64-bit Windows is much larger than 4GB, something I’ll describe shortly, Windows can give 32-bit processes the maximum 4GB that they can address and use the rest for the operating system’s virtual memory. If you run Testlimit on 64-bit Windows, you’ll see it consume the entire 32-bit addressable address space:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_24.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_11.png" width="468" height="128" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;64-bit processes use 64-bit pointers, so their theoretical maximum address space is 16 exabytes (2^64). However, Windows doesn’t divide the address space evenly between the active process and the system, but instead defines a region in the address space for the process and others for various system memory resources, like system page table entries (PTEs), the file cache, and paged and non-paged pools. &lt;/p&gt;  &lt;p&gt;The size of the process address space is different on IA64 and x64 versions of Windows where the sizes were chosen by balancing what applications need against the memory costs of the overhead (page table pages and translation lookaside buffer - TLB - entries) needed to support the address space. On x64, that’s 8192GB (8TB) and on IA64 it’s 7168GB (7TB - the 1TB difference from x64 comes from the fact that the top level page directory on IA64 reserves slots for Wow64 mappings). On both IA64 and x64 versions of Windows, the size of the various resource address space regions is 128GB (e.g. non-paged pool is assigned 128GB of the address space), with the exception of the file cache, which is assigned 1TB. The address space of a 64-bit process therefore looks something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_2.png" width="90" height="200" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The figure isn’t drawn to scale, because even 8TB, much less 128GB, would be a small sliver. Suffice it to say that like our universe, there’s a lot of emptiness in the address space of a 64-bit process. &lt;/p&gt;  &lt;p&gt;When you run the 64-bit version of Testlimit (Testlimit64) on 64-bit Windows with the –r switch, you’ll see it consume 8TB, which is the size of the part of the address space it can manage:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_26.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_12.png" width="473" height="122" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_28.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_13.png" width="316" height="47" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;h3&gt;Committed Memory&lt;/h3&gt;  &lt;p&gt;Testlimit’s –r switch has it reserve virtual memory, but not actually &lt;em&gt;commit&lt;/em&gt; it. Reserved virtual memory can’t actually store data or code, but applications sometimes use a reservation to create a large block of virtual memory and then commit it as needed to ensure that the committed memory is contiguous in the address space. When a process commits a region of virtual memory, the operating system guarantees that it can maintain all the data the process stores in the memory either in physical memory or on disk.&amp;#160; That means that a process can run up against another limit: the &lt;em&gt;commit limit&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;As you’d expect from the description of the commit guarantee, the commit limit is the sum of physical memory and the sizes of the paging files. In reality, not quite all of physical memory counts toward the commit limit since the operating system reserves part of physical memory for its own use. The amount of committed virtual memory for all the active processes, called the &lt;em&gt;current commit charge&lt;/em&gt;, cannot exceed the system commit limit. When the commit limit is reached, virtual allocations that commit memory fail. That means that even a standard 32-bit process may get virtual memory allocation failures before it hits the 2GB address space limit.&lt;/p&gt;  &lt;p&gt;The current commit charge and commit limit is tracked by Process Explorer in its System Information window in the Commit Charge section and in the Commit History bar chart and graph:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_8.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_3.png" width="233" height="80" /&gt;&lt;/a&gt;&amp;#160; &lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_30.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_14.png" width="180" height="120" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Task Manager prior to Vista and Windows Server 2008 shows the current commit charge and limit similarly, but calls the current commit charge &amp;quot;PF Usage&amp;quot; in its graph:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_6.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_2.png" width="373" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On Vista and Server 2008, Task Manager doesn't show the commit charge graph and labels the current commit charge and limit values with &amp;quot;Page File&amp;quot; (despite the fact that they will be non-zero values even if you have no paging file):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_4.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_1.png" width="184" height="104" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can stress the commit limit by running Testlimit with the -m switch, which directs it to allocate committed memory. The 32-bit version of Testlimit may or may not hit its address space limit before hitting the commit limit, depending on the size of physical memory, the size of the paging files and the current commit charge when you run it. If you're running 32-bit Windows and want to see how the system behaves when you hit the commit limit, simply run multiple instances of Testlimit until one hits the commit limit before exhausting its address space. &lt;/p&gt;  &lt;p&gt;Note that, by default, the paging file is configured to grow, which means that the commit limit will grow when the commit charge nears it. And even when when the paging file hits its maximum size, Windows is holding back some memory and its internal tuning, as well as that of applications that cache data, might free up more. Testlimit anticipates this and when it reaches the commit limit, it sleeps for a few seconds and then tries to allocate more memory, repeating this indefinitely until you terminate it.&lt;/p&gt;  &lt;p&gt;If you run the 64-bit version of Testlimit, it will almost certainly will hit the commit limit before exhausting its address space, unless physical memory and the paging files sum to more than 8TB, which as described previously is the size of the 64-bit application-accessible address space. Here's the partial output of the 64-bit Testlimit&amp;#160; running on my 8GB system (I specified an allocation size of 100MB to make it leak more quickly):&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb.png" width="554" height="301" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And here's the commit history graph with steps when Testlimit paused to allow the paging file to grow:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_16.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_3.png" width="249" height="131" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When system virtual memory runs low, applications may fail and you might get strange error messages when attempting routine operations. In most cases, though, Windows will be able present you the low-memory resolution dialog, like it did for me when I ran this test:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image30.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image30_thumb.png" width="324" height="252" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After you exit Testlimit, the commit limit will likely drop again when the memory manager truncates the tail of the paging file that it created to accommodate Testlimit's extreme commit requests. Here, Process Explorer shows that the current limit is well below the peak that was achieved when Testlimit was running:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_16.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_7.png" width="181" height="121" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Process Committed Memory&lt;/h3&gt;  &lt;p&gt;Because the commit limit is a global resource whose consumption can lead to poor performance, application failures and even system failure, a natural question is 'how much are processes contributing the commit charge'? To answer that question accurately, you need to understand the different types of virtual memory that an application can allocate. &lt;/p&gt;  &lt;p&gt;Not all the virtual memory that a process allocates counts toward the commit limit. As you've seen, reserved virtual memory doesn't. Virtual memory that represents a file on disk, called a file mapping view, also doesn't count toward the limit unless the application asks for copy-on-write semantics, because Windows can discard any data associated with the view from physical memory and then retrieve it from the file. The virtual memory in Testlimit's address space where its executable and system DLL images are mapped therefore don't count toward the commit limit. There are two types of process virtual memory that do count toward the commit limit: private and pagefile-backed. &lt;/p&gt;  &lt;p&gt;Private virtual memory is the kind that underlies the garbage collector heap, native heap and language allocators. It's called private because by definition it can't be shared between processes. For that reason, it's easy to attribute to a process and Windows tracks its usage with the Private Bytes performance counter. Process Explorer displays a process private bytes usage in the Private Bytes column, in the Virtual Memory section of the Performance page of the process properties dialog, and displays it in graphical form on the Performance Graph page of the process properties dialog. Here's what Testlimit64 looked like when it hit the commit limit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_18.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb.png" width="230" height="327" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_20.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_8.png" width="471" height="136" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Pagefile-backed virtual memory is harder to attribute, because it can be shared between processes. In fact, there's no process-specific counter you can look at to see how much a process has allocated or is referencing. When you run Testlimit with the -s switch, it allocates pagefile-backed virtual memory until it hits the commit limit, but even after consuming over 29GB of commit, the virtual memory statistics for the process don't provide any indication that it's the one responsible:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_22.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_9.png" width="205" height="133" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For that reason, I added the -l switch to Handle a while ago. A process must open a pagefile-backed virtual memory object, called a section, for it to create a mapping of pagefile-backed virtual memory in its address space. While Windows preserves existing virtual memory even if an application closes the handle to the section that it was made from, most applications keep the handle open.&amp;#160; The -l switch prints the size of the allocation for pagefile-backed sections that processes have open. Here's partial output for the handles open by Testlimit after it has run with the -s switch:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_26.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsofWindowsVirtualMemory_917D/image_thumb_11.png" width="394" height="234" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can see that Testlimit is allocating pagefile-backed memory in 1MB blocks and if you summed the size of all the sections it had opened, you'd see that it was at least one of the processes contributing large amounts to the commit charge.&lt;/p&gt;  &lt;h3&gt;How Big Should I Make the Paging File?&lt;/h3&gt;  &lt;p&gt;Perhaps one of the most commonly asked questions related to virtual memory is, how big should I make the paging file? There’s no end of ridiculous advice out on the web and in the newsstand magazines that cover Windows, and even Microsoft has published misleading recommendations. Almost all the suggestions are based on multiplying RAM size by some factor, with common values being 1.2, 1.5 and 2. Now that you understand the role that the paging file plays in defining a system’s commit limit and how processes contribute to the commit charge, you’re well positioned to see how useless such formulas truly are. &lt;/p&gt;  &lt;p&gt;Since the commit limit sets an upper bound on how much private and pagefile-backed virtual memory can be allocated concurrently by running processes, the only way to reasonably size the paging file is to know the maximum total commit charge for the programs you like to have running at the same time. If the commit limit is smaller than that number, your programs won’t be able to allocate the virtual memory they want and will fail to run properly. &lt;/p&gt;  &lt;p&gt;So how do you know how much commit charge your workloads require? You might have noticed in the screenshots that Windows tracks that number and Process Explorer shows it: Peak Commit Charge. To optimally size your paging file you should start all the applications you run at the same time, load typical data sets, and then note the commit charge peak (or look at this value after a period of time where you know maximum load was attained). Set the paging file minimum to be that value minus the amount of RAM in your system (if the value is negative, pick a minimum size to permit the kind of crash dump you are configured for). If you want to have some breathing room for potentially large commit demands, set the maximum to double that number. &lt;/p&gt;  &lt;p&gt;Some feel having no paging file results in better performance, but in general, having a paging file means Windows can write pages on the modified list (which represent pages that aren’t being accessed actively but have not been saved to disk) out to the paging file, thus making that memory available for more useful purposes (processes or file cache). So while there may be some workloads that perform better with no paging file, in general having one will mean more usable memory being available to the system (never mind that Windows won’t be able to write kernel crash dumps without a paging file sized large enough to hold them).&lt;/p&gt;  &lt;p&gt;Paging file configuration is in the System properties, which you can get to by typing “sysdm.cpl” into the Run dialog, clicking on the Advanced tab, clicking on the Performance Options button, clicking on the Advanced tab (this is &lt;em&gt;really&lt;/em&gt; advanced), and then clicking on the Change button:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_22.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/PushingtheLimitsVIrtualMemory_F6E0/image_thumb_7.png" width="550" height="302" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You’ll notice that the default configuration is for Windows to automatically manage the page file size. When that option is set on Windows XP and Server 2003,&amp;#160; Windows creates a single paging file that’s minimum size is 1.5 times RAM if RAM is less than 1GB, and RAM if it's greater than 1GB, and that has a maximum size that's three times RAM. On Windows Vista and Server 2008, the minimum is intended to be large enough to hold a kernel-memory crash dump and is RAM plus 300MB or 1GB, whichever is larger. The maximum is either three times the size of RAM or 4GB, whichever is larger. That explains why the peak commit on my 8GB 64-bit system that’s visible in one of the screenshots is 32GB. I guess whoever wrote that code got their guidance from one of those magazines I mentioned!&lt;/p&gt;  &lt;p&gt;A couple of final limits related to virtual memory are the maximum size and number of paging files supported by Windows. 32-bit Windows has a maximum paging file size of 16TB (4GB if you for some reason run in non-PAE mode) and 64-bit Windows can having paging files that are up to 16TB in size on x64 and 32TB on IA64. For all versions, Windows supports up to 16 paging files, where each must be on a separate volume. &lt;/p&gt;  &lt;h3&gt;Pushing the Limits of Windows&lt;/h3&gt;  &lt;p&gt;Other posts in this series include:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx"&gt;Pushing the Limits of Windows: Physical Memory&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx"&gt;Pushing the Limits of Windows: Paged and Nonpaged Pool&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx"&gt;Pushing the Limits of Windows: Processes and Threads&lt;/a&gt;&lt;/p&gt;   &lt;a href="http://blogs.technet.com/markrussinovich/archive/2009/09/29/3283844.aspx"&gt;Pushing the Limits of Windows: Handles&lt;/a&gt;&lt;/blockquote&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3155406" width="1" height="1"&gt;</description></item><item><title>The Case of the Slooooow System</title><link>http://blogs.technet.com/markrussinovich/archive/2008/09/24/3126858.aspx</link><pubDate>Wed, 24 Sep 2008 13:08:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3126858</guid><dc:creator>markrussinovich</dc:creator><slash:comments>151</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3126858.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3126858</wfw:commentRss><description>&lt;P&gt;A few weeks ago my wife complained that her Vista desktop was not responding to her typing or mouse clicks. Given the importance of the customer, I immediately sat down at the system to troubleshoot.&amp;nbsp; It wasn’t completely hung, but extremely sluggish. For example, the mouse moved and when I clicked on the start button the start menu opened after about 30 seconds. I suspected that something was hogging the CPU and likely could have resolved the problem simply by logging off or rebooting, but knew that if I didn’t determine the root cause and address it, she’d likely be calling on my technical support services again in the near future. In any case, stooping to that kind of troubleshooting hack is beneath my dignity. I therefore set out to investigate. &lt;/P&gt;
&lt;P&gt;My first step was to run &lt;A href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx"&gt;Process Explorer&lt;/A&gt; to see which process was using the CPU. After a few minutes Process Explorer finally appeared and showed that not one, but two processes were involved, each consuming 50% of the CPU: Iexplore.exe and Dllhost.exe. Iexplore is Internet Explorer (IE) and I suspected that IE itself wasn’t the problem, but that it was a browser helper object (BHO), ActiveX control, or some other plugin loaded into IE. Similarly, Dllhost.exe is the host process for out-of-process COM server DLLs, so it was probably not at fault, but the COM server loaded into it. Both required digging deeper and I decided to tackle IE first. &lt;/P&gt;
&lt;P&gt;In order to try and get some CPU headroom in which to operate, I suspended the Dllhost process by selecting it in Process Explorer, right-clicking to open the process context menu, and selecting the Suspend entry:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_34.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_34.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_16.png" width=325 height=250 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_16.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That put the Dllhost process to sleep and, as I expected, that freed up 50% of the CPU. That’s because the computer was a dual-core system and so to consume 100% of the available CPU cycles a process would have to have two threads, each hogging one of the cores. Most bugs I've seen that result in the CPU being pegged are caused by a single thread. &lt;/P&gt;
&lt;P&gt;Processes don’t execute code, threads do, so I needed to look inside the IE process to see what thread or threads were running. I double-clicked on Iexplore.exe in Process Explorer to open its process properties dialog and switched to the Threads page. Several threads were running, but one was dominating the CPU:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_32.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_32.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_15.png" width=441 height=109 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_15.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;From past experience I knew that Ieframe.dll was part of IE, but to be sure I clicked on the modules button on the Threads tab of the Properties dialog and switched to the Details page of the resulting Shell properties dialog:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_22.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_22.png"&gt;&lt;IMG border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_9.png" width=317 height=249 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_9.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The description didn't give me a clue as the thread's specific purpose, so I moved to the second clue about the thread, its start function. Because I had configured Process Explorer to retrieve symbols for Windows images from the Microsoft symbol server in Options-&amp;gt;Configure Symbols, Process Explorer showed the name of the function where each thread began executing. Sometimes the DLL or function where a thread starts executing is enough to identify the thread’s purpose or the software causing a problem. In this case, the thread began in a function named CTablWindow::_TabWindowThreadProc. The function name hints that it’s the one in which the main thread of a tab starts running, but that still wasn’t enough to tell me why the thread was running so much; I needed to dig even deeper and look inside the thread to see &lt;EM&gt;where&lt;/EM&gt; it was executing.&lt;/P&gt;
&lt;P&gt;To look at what the thread was up to, I double-clicked on it in the Threads list to open the Thread Stack dialog, which shows the functions on the thread’s stack. A stack is essentially an execution history, where each function listed called the one above it on the list and the function at the top of the list is the one most recently executed by the thread at the time of Process Explorer looks at the stack. I scrolled through the list, looking for frames that referenced 3rd-party DLLs or Microsoft IE plugins, since they would be far more likely to have a bug than IE’s own code. Sure enough, I found frames pointing at a popular 3rd-party ActiveX control, Adobe Flash:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_40.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_40.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_19.png" width=372 height=232 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_19.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Just to be sure that I hadn’t happened to catch Flash running when a different component was using most of the CPU time, I closed and reopened the stack dialog several times, but all of them pointed at Flash. &lt;/P&gt;
&lt;P&gt;The first thing I do when I suspect that some software is causing a problem is to check the vendor’s web site to make sure that I have the latest version. I opened the Process Explorer DLL view and looked at Flash.ocx’s version, went to Adobe’s site and looked at the version of the current Flash download, and they were the same.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I was at a dead end. I couldn’t know for sure if Flash had a bug or, more likely, there was a Flash application that had a bug, nor could I be sure that the problem wouldn’t recur. I tried to determine which site was hosting the Flash content by closing tabs one by one, but when I had close them all the thread was still running.&lt;/P&gt;
&lt;P&gt;At this point the only options I had were to uninstall Flash and leave my wife with a degraded web experience, or terminate IE to stop the current CPU usage and hope that it wouldn’t happen again. I chose the latter and the case remains open. Since investigating this I’ve seen the same Flash behavior again on my wife’s system and on my own, so have been vigilantly watching the Adobe site for a new version just in case its due to a bug in Flash itself. I was disappointed that there was no actionable result of the investigation, but at least I knew what had caused the CPU usage. &lt;/P&gt;
&lt;P&gt;I now turned my attention the Dllhost problem with the hope that I'd meet with better success. Process Explorer lists in a tooltip the component or components loaded into hosting processes like Svchost.exe (the Windows service host process), Rundll32 (the Control Panel applet hosting process), Taskeng.exe (the scheduled task hosting process on Vista and Server 2008), and Dllhost.exe. I moved the mouse over Dllhost.exe to see what COM server it was running:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_44.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_44.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_21.png" width=468 height=198 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_21.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;It was running the Thumbnail Cache COM server, whose job it is to create Explorer thumbnails for image and media files. It is part of Windows, so once again I had to look inside the process for more clues. I resumed the Dllhost process I had suspended earlier and opened the process properties threads page:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_48.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_48.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_23.png" width=582 height=165 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_23.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The thread consuming the most CPU in this case started in Quartz.dll’s ObjectThread function. I looked at its properties and saw that it was another Windows DLL, the DirectShow Runtime, with a generic function name:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_24.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_24.png"&gt;&lt;IMG border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_10.png" width=314 height=237 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_10.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Next, I double-clicked to look at the thread stack:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_50.png" mce_href="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_50.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_24.png" width=382 height=322 mce_src="https://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_F063/image_thumb_24.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The first few frames were in User32.dll and Ntdll.dll, core Windows system DLLs, but frames 4-7 are in the Sonicmp4demux.ax (".ax" is an extension commonly used for DirectShow filters), a 3rd-party component. The function names for those frames were the same and didn't make sense because the Microsoft symbol server only stores symbols for software included in Windows. Several more stack snapshots confirmed that it was the code causing the CPU usage. &lt;/P&gt;
&lt;P&gt;Now that I had my suspect, the next step was to check for a newer version. But first I had to figure out what software the DLL came with, which was harder than it seemed. I opened the DLL view to take a closer look at the version information, but the description didn't reveal anything:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image5.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image5.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image5_thumb.png" width=451 height=208 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image5_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;There were no folders in the Start menu or items in the Add/Remove Programs list with Sonic in the name. I Windows-Live-searched (I expect that word to be added to Webster's any day now) for Sonic and found that it's part of the Roxio's CD and DVD authoring software suites. I looked in the start menu and sure enough, found a Roxio folder:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_6.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_6.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_2.png" width=215 height=70 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I ran the Roxio software to check its version number and discovered that the Creator application includes a built-in facility to check for updates. I ran it, but it came up empty:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_8.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_8.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_3.png" width=427 height=114 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_3.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I checked the Roxio web site just to be sure and it turned out there was a newer version that the built-in updater hadn't offered, perhaps because the update, according to the page, didn't offer anything new:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image19.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image19.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image19_thumb.png" width=637 height=242 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image19_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I downloaded it anyway (all 640MB of it!) and waited the 15 or so minutes for it to install. Then I checked the version information of Sonicmp4demux.ax to see if it was newer, but its version number, 1.4.402.60802, was the same as the one I'd seen in the DLL view and the file was two years old:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_12.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_12.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_5.png" width=494 height=140 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_5.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I could have uninstalled the software, which would ensure that the problem wouldn't return, but I wanted to keep Roxio for its DVD authoring functionality. I didn't care if I didn't get thumbnails for Roxio-specific image formats - I wasn't even sure there were any I'd ever see in Explorer - so I set out to see if I could disable just the Sonic demultiplexer. I could have searched the Registry for the DLL name, which is surely where it was registered, but that's a brute-force approach and if there were indirect or multiple references I could easily end up disabling more than just its thumbnail generation and possibly breaking something in Windows. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor&lt;/A&gt; was the perfect tool for the job. Because I didn't know when the problem might reoccur - it might takes days to reproduce - I didn't want to just run it and let it consume all available virtual memory or disk space, so I set the History Depth in the Options menu to have Process Monitor retain only the most recent 1 million events:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_16.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_16.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_7.png" width=348 height=133 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_7.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I also set an Include filter for paths matching C:\Windows\System32\Dllhost.exe, minimized it, and let my wife have the system back. &lt;/P&gt;
&lt;P&gt;The next day I came home from work, sat down at the computer and saw from Process Explorer that Dllhost.exe was back at it, consuming 50% of the CPU. I suspect that because it's a dual-core system, the problem had been showing up regularly, but my wife hadn't noticed it because the remaining CPU capacity was enough to mask it (another good reason to buy multi-core processors!). I brought Process Monitor to the foreground and noted it had seen 114,000 Dllhost operations, which was obviously way too many to scan through individually. I searched for "sonicmp4" and found a reference in a Registry query near the end of the trace:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_14.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_14.png"&gt;&lt;IMG border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb.png" width=550 height=74 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The query is of a COM object registration for the demultiplexer. Because the COM object is a 3rd-party DLL, I was certain that that COM Class ID (CLSID) isn't hard-coded into Windows, so I went back to the first entry in the trace and searched for "A7DD215", the first few characters of the CLSID. The search found a match a few thousand operations earlier:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_18.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_18.png"&gt;&lt;IMG border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_6.png" width=550 height=113 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_6.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The CLSID was in the name of a Registry key under another COM object registration. I Windows-Live-searched (that just rolls off the tongue, doesn't it?) for the parent CLSID and found this KB article that explains that the registry key is where &lt;A href="http://en.wikipedia.org/wiki/DirectShow" mce_href="http://en.wikipedia.org/wiki/DirectShow"&gt;DirectShow&lt;/A&gt; filters register: &lt;A title=http://msdn.microsoft.com/en-us/library/ms787560(VS.85).aspx href="http://msdn.microsoft.com/en-us/library/ms787560(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms787560(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms787560(VS.85).aspx&lt;/A&gt;&amp;nbsp; I took a look at the stack for the particular query to confirm that's the reason Dllhost was reading from there:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_20.png" mce_href="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_20.png"&gt;&lt;IMG border=0 alt=image src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_8.png" width=382 height=332 mce_src="http://blogs.technet.com/blogfiles/markrussinovich/WindowsLiveWriter/TheCaseoftheSlowSystem_89F3/image_thumb_8.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I was now confident that I could simply rename the Sonic filter registration key to prevent its use. I never delete registry keys when performing this kind of troubleshooting just in case the change disables important functionality or somehow breaks something else. I had seen from the traces that the thumbnail cache generator had come across an AVI file that caused it to load the Sonic demultiplexer, a format Windows is obviously able to handle on its own, so I was pretty sure things would continue to work. After terminating the Dllhost and making the change, I browsed to the same folder, deleted the thumbnails, and confirmed that there was no reduced functionality as far as I could tell. I then used Roxio to successfully burn a DVD with a number of AVI files. This case was closed.&lt;/P&gt;
&lt;P&gt;My wife's system was now usable again, and though I wasn't able to close the Flash-related part of the case, at least I knew the cause and could keep an eye out for updates. More importantly, by solving the Dllhost part of the case, even if Flash went crazy again, her system would still be usable and she wouldn't be filing a critical support incident for it with me - thanks to Process Explorer and Process Monitor.&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3126858" width="1" height="1"&gt;</description></item><item><title>Where in the World is Mark Russinovich?</title><link>http://blogs.technet.com/markrussinovich/archive/2008/09/08/3121087.aspx</link><pubDate>Mon, 08 Sep 2008 21:05:54 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3121087</guid><dc:creator>markrussinovich</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.technet.com/markrussinovich/comments/3121087.aspx</comments><wfw:commentRss>http://blogs.technet.com/markrussinovich/commentrss.aspx?PostID=3121087</wfw:commentRss><description>&lt;p&gt;I haven't had a chance to write a new post in a while because I've been busy working on Windows, new Sysinternals tools and enhancements to existing ones, and the 5th edition of Windows Internals, so I thought that I'd update you on my speaking schedule, book status, and what's going on at Sysinternals.&lt;/p&gt;  &lt;p&gt;My next event is one that anyone can easily attend live, or via recorded webcast: it's the third virtual roundtable in the Microsoft Springboard series of round tables I've been hosting. &lt;a href="http://technet.microsoft.com/en-us/windows/aa904820.aspx"&gt;Springboard&lt;/a&gt; is program designed to connect IT pros with practical information, guidance and tools to help them in their evaluation and deployment of Windows without marketing fluff getting in the way. This next round table is on September 24 and takes on the topic of performance. As usual, we'll have a panel of MVPs and customers sharing their experiences and real world tips with you. You can sign up to watch it live and find the contact to send in your questions ahead of time &lt;a href="https://ms.istreamplanet.com/springboard/"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In addition to the round table, I've got a full conference schedule for the Fall, including three keynotes:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://www.microsoft.com/hk/technet/teched2008/default.aspx"&gt;TechEd Hong Kong&lt;/a&gt;, October 8-10, Wanchai, Hong Kong&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.virtualization.info/virtualizationcongress2008/"&gt;Virtualization Congress&lt;/a&gt;, October 15-16, London, UK&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blogs.msdn.com/platforma2009/"&gt;Microsoft Platforma&lt;/a&gt;, December 4-5, Moscow, Russia&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I'm also returning to one of my favorite conferences, TechEd EMEA IT Pros. I love reconnecting with my speaker friends, the enthusiastic European attendees, and Barcelona. I'm delivering several sessions, including an updated &amp;quot;&lt;a href="http://www.microsoft.com/emea/spotlight/sessionh.aspx?videoid=722"&gt;The Case of the Unexplained...&lt;/a&gt;&amp;quot;, complete with all new examples.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://www.microsoft.com/emea/teched2008/itpro/default.aspx"&gt;TechEd EMEA IT Pro&lt;/a&gt;, November 3-7, Barcelona, Spain&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I hope to see you at one of these events, and if attend one of my sessions please stop by and say hello. &lt;/p&gt;  &lt;p&gt;The book, which is updated to focus exclusively on Windows Vista and Windows Server 2008, is well along and we're on track for publication in January. I'm writing it again with &lt;a href="http://www.solsem.com/"&gt;David Solomon&lt;/a&gt;, my coauthor on the previous two editions, and &lt;a href="http://www.alex-ionescu.com/"&gt;Alex Ionescu&lt;/a&gt;, who is new to this edition and contributing great content. With all the new information and experiments, the book is going to be around 250 pages longer, making it its bed-time reading value stretch even longer. You can find information on the book on its official home page &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Finally, Bryce and I have some exciting Sysinternals updates, including a major Process Monitor update and enhancements to Process Explorer, planned for release in the coming weeks and months.&lt;/p&gt;  &lt;p&gt;If you'd like to hear directly from me on what I'm up to at Microsoft, what's behind the Sysinternals operation, what new feature we're releasing in Process Monitor, and my views on Windows, operating system security, and more, check out my recent &lt;a href="http://edge.technet.com/Media/Interview-with-Mark-Russinovich-the-future-of-Sysinternals-Security-Windows/"&gt;interview with TechNet Edge&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3121087" width="1" height="1"&gt;</description></item></channel></rss>