Desktop Heap Overview


Desktop heap is probably not something that you spend a lot of time thinking about, which is a good thing.  However, from time to time you may run into an issue that is caused by desktop heap exhaustion, and then it helps to know about this resource.  Let me state up front that things have changed significantly in Vista around kernel address space, and much of what I’m talking about today does not apply to Vista.


Laying the groundwork: Session Space

To understand desktop heap, you first need to understand session space.  Windows 2000, Windows XP, and Windows Server 2003 have a limited, but configurable, area of memory in kernel mode known as session space.  A session represents a single user’s logon environment.  Every process belongs to a session.  On a Windows 2000 machine without Terminal Services installed, there is only a single session, and session space does not exist.  On Windows XP and Windows Server 2003, session space always exists.  The range of addresses known as session space is a virtual address range.  This address range is mapped to the pages assigned to the current session.  In this manner, all processes within a given session map session space to the same pages, but processes in another session map session space to a different set of pages. 

Session space is divided into four areas: session image space, session structure, session view space, and session paged pool.  Session image space loads a session-private copy of Win32k.sys modified data, a single global copy of win32k.sys code and unmodified data, and maps various other session drivers like video drivers, TS remote protocol driver, etc.  The session structure holds various memory management (MM) control structures including the session working set list (WSL) information for the session.  Session paged pool allows session specific paged pool allocations.  Windows XP uses regular paged pool, since the number of remote desktop connections is limited.  On the other hand, Windows Server 2003 makes allocations from session paged pool instead of regular paged pool if Terminal Services (application server mode) is installed.  Session view space contains mapped views for the session, including desktop heap. 

Session Space layout:

Session Image Space: win32k.sys, session drivers

Session Structure: MM structures and session WSL

Session View Space: session mapped views, including desktop heap

Session Paged Pool


Sessions, Window Stations, and Desktops

You’ve probably already guessed that desktop heap has something to do with desktops.  Let’s take a minute to discuss desktops and how they relate to sessions and window stations.  All Win32 processes require a desktop object under which to run.  A desktop has a logical display surface and contains windows, menus, and hooks.  Every desktop belongs to a window station.  A window station is an object that contains a clipboard, a set of global atoms and a group of desktop objects.  Only one window station per session is permitted to interact with the user. This window station is named “Winsta0.”  Every window station belongs to a session.  Session 0 is the session where services run and typically represents the console (pre-Vista).  Any other sessions (Session 1, Session 2, etc) are typically remote desktops / terminal server sessions, or sessions attached to the console via Fast User Switching.  So to summarize, sessions contain one or more window stations, and window stations contain one or more desktops.

You can picture the relationship described above as a tree.  Below is an example of this desktop tree on a typical system:

– Session 0

|   |

|   —- WinSta0           (interactive window station)

|   |      |

|   |      —- Default    (desktop)

|   |      |

|   |      —- Disconnect (desktop)

|   |      |

|   |      —- Winlogon   (desktop)

|   |

|   —- Service-0x0-3e7$  (non-interactive window station)

|   |      |

|   |      —- Default    (desktop)

|   |

|   —- Service-0x0-3e4$  (non-interactive window station)

|   |      |

|   |      —- Default    (desktop)

|   |

|   —- SAWinSta          (non-interactive window station)

|   |      |

|   |      —- SADesktop  (desktop)

|   |

– Session 1

|   |

|   —- WinSta0           (interactive window station)

|   |      |

|   |      —- Default    (desktop)

|   |      |

|   |      —- Disconnect (desktop)

|   |      |

|   |      —- Winlogon   (desktop)

|   |

– Session 2


    —- WinSta0           (interactive window station)


           —- Default    (desktop)


           —- Disconnect (desktop)


           —- Winlogon   (desktop)


In the above tree, the full path to the SADesktop (as an example) can be represented as “Session 0\SAWinSta\SADesktop”.


Desktop Heap – what is it, what is it used for?

Every desktop object has a single desktop heap associated with it.  The desktop heap stores certain user interface objects, such as windows, menus, and hooks.  When an application requires a user interface object, functions within user32.dll are called to allocate those objects.  If an application does not depend on user32.dll, it does not consume desktop heap.  Let’s walk through a simple example of how an application can use desktop heap. 

1.     An application needs to create a window, so it calls CreateWindowEx in user32.dll.

2.     User32.dll makes a system call into kernel mode and ends up in win32k.sys.

3.     Win32k.sys allocates the window object from desktop heap

4.     A handle to the window (an HWND) is returned to caller

5.     The application and other processes in the same session can refer to the window object by its HWND value


Where things go wrong

Normally this “just works”, and neither the user nor the application developer need to worry about desktop heap usage.  However, there are two primary scenarios in which failures related to desktop heap can occur:

  1. Session view space for a given session can become fully utilized, so it is impossible for a new desktop heap to be created.

  2. An existing desktop heap allocation can become fully utilized, so it is impossible for threads that use that desktop to use more desktop heap.


So how do you know if you are running into these problems?  Processes failing to start with a STATUS_DLL_INIT_FAILED (0xC0000142) error in user32.dll is a common symptom.  Since user32.dll needs desktop heap to function, failure to initialize user32.dll upon process startup can be an indication of desktop heap exhaustion.  Another symptom you may observe is a failure to create new windows.  Depending on the application, any such failure may be handled in different ways.  Note that if you are experiencing problem number one above, the symptoms would usually only exist in one session.  If you are seeing problem two, then the symptoms would be limited to processes that use the particular desktop heap that is exhausted.


Diagnosing the problem

So how can you know for sure that desktop heap exhaustion is your problem?  This can be approached in a variety of ways, but I’m going to discuss the simplest method for now.  Dheapmon is a command line tool that will dump out the desktop heap usage for all the desktops in a given session.  See our first blog post for a list of tool download locations.  Once you have dheapmon installed, be sure to run it from the session where you think you are running out of desktop heap.  For instance, if you have problems with services failing to start, then you’ll need to run dheapmon from session 0, not a terminal server session.

Dheapmon output looks something like this:

Desktop Heap Information Monitor Tool (Version 7.0.2727.0)

Copyright (c) 2003-2004 Microsoft Corp.


  Session ID:    0 Total Desktop: (  5824 KB –    8 desktops)


  WinStation\Desktop            Heap Size(KB)    Used Rate(%)


  WinSta0\Default                    3072              5.7

  WinSta0\Disconnect                   64              4.0

  WinSta0\Winlogon                    128              8.7

  Service-0x0-3e7$\Default            512             15.1

  Service-0x0-3e4$\Default            512              5.1

  Service-0x0-3e5$\Default            512              1.1

  SAWinSta\SADesktop                  512              0.4

  __X78B95_89_IW\__A8D9S1_42_ID       512              0.4



As you can see in the example above, each desktop heap size is specified, as is the percentage of usage.  If any one of the desktop heaps becomes too full, allocations within that desktop will fail.  If the cumulative heap size of all the desktops approaches the total size of session view space, then new desktops cannot be created within that session.  Both of the failure scenarios described above depend on two factors: the total size of session view space, and the size of each desktop heap allocation.  Both of these sizes are configurable. 


Configuring the size of Session View Space

Session view space size is configurable using the SessionViewSize registry value.  This is a REG_DWORD and the size is specified in megabytes.  Note that the values listed below are specific to 32-bit x86 systems not booted with /3GB.  A reboot is required for this change to take effect.  The value should be specified under:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management


Size if no registry value configured

Default registry value

Windows 2000 *

20 MB


Windows XP

20 MB

48 MB

Windows Server 2003

20 MB

48 MB

* Settings for Windows 2000 are with Terminal Services enabled and hotfix 318942 installed.  Without the Terminal Services installed, session space does not exist, and desktop heap allocations are made from a fixed 48 MB region for system mapped views.  Without hotfix 318942 installed, the size of session view space is fixed at 20 MB.

The sum of the sizes of session view space and session paged pool has a theoretical maximum of slightly under 500 MB for 32-bit operating systems.  The maximum varies based on RAM and various other registry values.  In practice the maximum value is around 450 MB for most configurations.  When the above values are increased, it will result in the virtual address space reduction of any combination of nonpaged pool, system PTEs, system cache, or paged pool.


Configuring the size of individual desktop heaps

Configuring the size of the individual desktop heaps is bit more complex.  Speaking in terms of desktop heap size, there are three possibilities:

·         The desktop belongs to an interactive window station and is a “Disconnect” or “Winlogon” desktop, so its heap size is fixed at 64KB or 128 KB, respectively (for 32-bit x86)

·         The desktop heap belongs to an interactive window station, and is not one of the above desktops.  This desktop’s heap size is configurable.

·         The desktop heap belongs to a non-interactive window station.  This desktop’s heap size is also configurable.


The size of each desktop heap allocation is controlled by the following registry value:

            HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows


 The default data for this registry value will look something like the following (all on one line):

               %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows

               SharedSection=1024,3072,512 Windows=On SubSystemType=Windows

               ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3

               ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off




The numeric values following “SharedSection=” control how desktop heap is allocated. These SharedSection values are specified in kilobytes.

The first SharedSection value (1024) is the shared heap size common to all desktops. This memory is not a desktop heap allocation, and the value should not be modified to address desktop heap problems.

The second SharedSection value (3072) is the size of the desktop heap for each desktop that is associated with an interactive window station, with the exception of the “Disconnect” and “Winlogon” desktops.

The third SharedSection value (512) is the size of the desktop heap for each desktop that is associated with a “non-interactive” window station. If this value is not present, the size of the desktop heap for non-interactive window stations will be same as the size specified for interactive window stations (the second SharedSection value). 

Consider the two desktop heap exhaustion scenarios described above.  If the first scenario is encountered (session view space is exhausted), and most of the desktop heaps are non-interactive, then the third SharedSection can be decreased in an effort to allow more (smaller) non-interactive desktop heaps to be created.  Of course, this may not be an option if the processes using the non-interactive heaps require a full 512 KB.  If the second scenario is encountered (a single desktop heap allocation is full), then the second or third SharedSection value can be increased to allow each desktop heap to be larger than 3072 or 512 KB.  A potential problem with this is that fewer total desktop heaps can be created.


What are all these window stations and desktops in Session 0 anyway?

Now that we know how to tweak the sizes of session view space and the various desktops, it is worth talking about why you have so many window stations and desktops, particularly in session 0.  First off, you’ll find that every WinSta0 (interactive window station) has at least 3 desktops, and each of these desktops uses various amounts of desktop heap.  I’ve alluded to this previously, but to recap, the three desktops for each interactive window stations are:

·         Default desktop – desktop heap size is configurable as described below

·         Disconnect desktop – desktop heap size is 64k on 32-bit systems

·         Winlogon desktop – desktop heap size is 128k on 32-bit systems


Note that there can potentially be more desktops in WinSta0 as well, since any process can call CreateDesktop and create new desktops.

Let’s move on to the desktops associated with non-interactive window stations: these are usually related to a service.  The system creates a window station in which service processes that run under the LocalSystem account are started. This window station is named service-0x0-3e7$. It is named for the LUID for the LocalSystem account, and contains a single desktop that is named Default. However, service processes that run as LocalSystem interactive start in Winsta0 so that they can interact with the user in Session 0 (but still run in the LocalSystem context).

Any service process that starts under an explicit user or service account has a window station and desktop created for it by service control manager, unless a window station for its LUID already exists. These window stations are non-interactive window stations.  The window station name is based on the LUID, which is unique for every logon.  If an entity (other than System) logs on multiple times, a new window station is created for each logon.  An example window station name is “service-0x0-22e1$”.

A common desktop heap issue occurs on systems that have a very large number of services.  This can be a large number of unique services, or one (poorly designed, IMHO) service that installs itself multiple times.  If the services all run under the LocalSystem account, then the desktop heap for Session 0\Service-0x0-3e7$\Default may become exhausted.  If the services all run under another user account which logs on multiples times, each time acquiring a new LUID, there will be a new desktop heap created for every instance of the service, and session view space will eventually become exhausted.

Given what you now know about how service processes use window stations and desktops, you can use this knowledge to avoid desktop heap issues.  For instance, if you are running out of desktop heap for the Session 0\Service-0x0-3e7$\Default desktop, you may be able to move some of the services to a new window station and desktop by changing the user account that the service runs under.


Wrapping up

I hope you found this post interesting and useful for solving those desktop heap issues!  If you have questions are comments, please let us know.


– Matthew Justice


[Update: 7/5/2007 – Desktop Heap, part 2 has been posted]

[Update: 9/13/2007 – Talkback video: Desktop Heap has been posted]

[Update: 3/20/2008 – The default interactive desktop heap size has been increased on 32-bit Vista SP1]


Comments (101)

  1. Joseph Biron says:

    This was a great primer on a part of Windows memory management that is seldom covered. Thanks!

  2. Thomas says:

    Is there a possibility of describing how this works under Vista, and providing a Vista-compatible version of dheapmon?

    I often have up to 20 IE tabs open on Vista, and with a few other applications (eg Outlook, Excel, Word), I seem to be hitting some resource limit, as new windows often fail to be created (unless I close some old ones).

  3. mptock says:

    My desktop heap numbers are these below. What numbers can I change, and to what value to correct my computer from not functioning properly after I have a certain amount of programs and web sites opened on it, when I still have plently of physical memory

    SharedSection=1024,3072,512 Windows

  4. ntdebug says:

    Thomas – A future post on desktop heap in Vista is definitely a possibility.  Keep an eye on our blog for this content.

  5. ntdebug says:

    mptock – The SharedSection numbers you have listed are the defaults on x86.  Please take a look at the “Configuring the size of individual desktop heaps” section above to understand what each of these numbers mean.  Any changes you may need to make to the values on your system will depend on what exactly is failing on your computer.  You can use Dheapmon (described above) to monitor desktop heap usage and determine if the problems you are seeing are related to desktop heap.

  6. If you have a lot of applications open one thing you might notice is that Windows — even XP — will

  7. Interesting – I hit the same issues with lots of tabs open in IE. To verify this was the problem I wanted to run dheapmon, but wasn’t sure it worked on Vista (since the docs say it’s version dependent and there is no Vista version), so I booted in debug mode, ran Windbg and connected in local kernel debug mode (that requires booting in debug mode – XP/2003 did not require that), and used the !dskheap command.

    See details below.

    I am about to reboot increasing the second number from 3076 to 4096.  We’ll see.

    –Dave Solomon

    coauthor, Windows Internals 4th edition


    Before starting IE:

    lkd> !dskheap

     WinstationDesktop  Heap Size(KB) Used Rate(%)


    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8636883c, UniStr = 86327020

    (000002B8: name not accessible)     3072  15%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 86327024, UniStr = 8639c020

    (000002B8: name not accessible)       64   3%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8639c024, UniStr = 863332e8

    (000002B8: name not accessible)      128   3%


      Total Desktop: (    3264 KB –   3 desktops)

      Session ID:  1


    After opening about 40-ish tabs:

    lkd> !dskheap

     WinstationDesktop  Heap Size(KB) Used Rate(%)


    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8636883c, UniStr = 86327020

    (000002B8: name not accessible)     3072  86%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 86327024, UniStr = 8639c020

    (000002B8: name not accessible)       64   3%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8639c024, UniStr = 863332e8

    (000002B8: name not accessible)      128   3%


      Total Desktop: (    3264 KB –   3 desktops)

      Session ID:  1


    Then tried to open several more tabs and ran out:

    lkd> !dskheap

     WinstationDesktop  Heap Size(KB) Used Rate(%)


    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8636883c, UniStr = 86327020

    (000002B8: name not accessible)     3072  99%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 86327024, UniStr = 8639c020

    (000002B8: name not accessible)       64   3%

    pUniStr = 8636eb9c, UniStr = 86333490

     (000002B8: name not accessible)pUniStr = 8639c024, UniStr = 863332e8

    (000002B8: name not accessible)      128   3%


      Total Desktop: (    3264 KB –   3 desktops)

      Session ID:  1


  8. Chad V. says:

    DHEAPMON shows the percentage of desktop heap that has been consumed;  is it possible to do the same thing programmatically, such that an application could display a warning when, say, 85% of the desktop heap has been consumed?

    Assume the following:  

    1)  our vendor’s application creates many windows

    2)  the application can create enough windows to totally deplete the desktop heap

    3)  when a window fails to open due to depleted desktop heap, the entire application crashes.

    4)  we do not want the application to crash;  we want to give the user the opportunity to close some windows to free up some heap and continue.

    5)  the vendor cannot detect that a window failed to open and handle the failure gracefully.  (This point cannot be argued:  while it may be possible to do, this vendor cannot do it.  Trust me. )

    They’ve already implemented a similar "warn before failure" methodology for the per-process user object handle quota (another application-crash point of failure), and they’re talking about doing the same for desktop heap.  Is it even possible?


  9. ntdebug says:

    Chad – there is no programmatic interface for querying the desktop heap usage.  dheapmon.exe actually relies on a kernel mode driver, dheapdmp.sys, to gather the information about the desktop heaps.  Unfortunately for the vendor you are working with, the right way to handle this is to gracefully handle the failure to create a window.  Since desktop heap is an internal implementation detail of win32k.sys, a user mode application should not rely on the status of a desktop heap as a means of deciding what operations it should perform.  Window creation ends up in the API function CreateWindow(Ex).  If the application developer is creating this window by directly calling this function, the return value can be checked to validate that the window was successfully creating before continuing.  Below is a snippet from an MSDN sample showing this…


        hwnd = CreateWindow(

            “MainWClass”,        // name of window class

            “Sample”,            // title-bar string

            WS_OVERLAPPEDWINDOW, // top-level window

            CW_USEDEFAULT,       // default horizontal position

            CW_USEDEFAULT,       // default vertical position

            CW_USEDEFAULT,       // default width

            CW_USEDEFAULT,       // default height

            (HWND) NULL,         // no owner window

            (HMENU) NULL,        // use class menu

            hinstance,           // handle to application instance

            (LPVOID) NULL);      // no window-creation data


        if (!hwnd)

            return FALSE;



  10. Ohad Israeli says:


    dheapmon failed to install on Vista 32, is there a version that is compatible with Vista ?

  11. ntdebug says:

    Ohad – There is currently no version of dheapmon for Vista.

  12. KPark says:

    Is there a way to globally monitor heap usage for all sessions?  I administer Windows 2003 Terminal servers, and I would like to monitor my users for heap exhaustion.  There appears to be paged and non-paged pool session counters in Perfmon for the Terminal Services Session object, but nothing about desktop heap space.

  13. ntdebug says:

    KPark – Current dheapmon is the only Microsoft tool for monitoring desktop heap, and it isn’t designed for monitoring multiple sessions / servers simultaneously.  This is a question that comes up periodically, and it is something that we have definitely talked about.  Generally we find that desktop heap usage is fairly consistent for a given workload, so if you take a series of dheapmon snapshot of a typical user’s session, you can get a feeling for what kind of desktop heap configuration you’ll need for your users.

    Regarding the perfmon counters for session pool, those values probably don’t mean what you think they mean.  The numbers are actually the sum of process pool quotas per session.  So only pool allocations that were charged to a process (via ExAllocatePoolWithQuotaTag) are included in the perfmon counter values.

  14. sagman says:

    The article states "Note that the values listed below are specific to 32-bit x86 systems not booted with /3GB or /PAE"  — we are booting with the /3GB switch, and I see that the registry entry for SessionViewSize is 48MB.  After running dheapmon it appears that we are only utilizing 16MB of desktop heap.  When I try to start a new Windows service using a User account, it fails, so I’m wondering if the 48MB is a reliable figure — is there a way to query the maximum desktop heap available?  BTW the service starts just fine under LOCAL SYSTEM, and stopping another service running under a user account allows me to start the service under a user account, so we’re 99% certain that this is a desktop heap issue.  We’re Windows 2003 Standard.

  15. ntdebug says:

    sagman  – This certainly could be a desktop heap problem.  Specifically, it sounds you like you have exhausted session view space (the memory region where desktop heaps come from).  With 3GB enabled, the size of session view space is fixed at 20 MB.  It cannot be configured due to the constraints on kernel address space when booted 3GB.  You can see the size of session view space in a kernel debugger (or using LiveKd) by examining the value of nt!MmSessionViewSize like this…


    // Dump out the value of the global variable…

    lkd> dd nt!MmSessionViewSize L1

    808ad254  03000000

    // Convert it to from hex bytes to decimal MB

    lkd> ? 03000000 / 400 / 400

    Evaluate expression: 48 = 00000030

    // So this system’s session view size is 48MB.


    If 16MB of your 20 MB session view space is used by desktop heap, session view space may be nearly consumed, since GDI also uses session view space.   Depending on how “full” each of your desktop heaps are, you may be able to tweak the SharedSection values to allow more, smaller, desktop heaps.  

  16. sagman says:

    Many thanks ntdebug for both the excellent post and the quality response(s).  Our solution was to "don’t do that" — we will avoid running so many sessions.  Our heaps were very small percentages so we could have tweaked the values but we were concerned because the server runs SQL Server under a user account (for security reasons) and we didn’t want to cause a problem with SQL Server.  In our particular case we were running multiple instances of services that were nearly identical; we rewrote the software to run as a single service and all is well.  Thanks again!

  17. Erres says:

    Great article.

    One question. I’m running a server with a lot of services running under LocalSystem. The non-interactive desktop-heap size is 512 Kb. All the space is in use, so I should allocate more space for non-interactive desktop heap.

    What are the concequenses?

    I’m not near the limit of 48 Mb, so that’s not an issue, but are there any risks (performance wise or so)?

  18. ntdebug says:


    I’m glad you enjoyed the article.  The main concern with increasing the sizes of the non-interactive desktop heaps is exhaustion of session view space.  Otherwise increasing the desktop heap size should not adversely affect your system.  Keep in mind that increasing the 512KB value will increase the heap size of all the non-interactive heaps, not just the one for LocalSystem services.

  19. Leonard Vaynerman says:

    What controls size for

    WinSta0Disconnect    and

    WinSta0Winlogon  desktop heap?

  20. ntdebug says:

    Leonard – The disconnect and winlogon desktop heaps both have a fixed size.  On 32-bit Windows the winlogon desktop heap is 128 KB, and the disconnect desktop heap is 64 KB.  On 64-bit Windows the sizes are increased by 50%, making the winlogon desktop heap 192 KB, and the disconnect desktop heap 96 KB.

  21. Josh Straub says:

    [Moderator’s note: The following is an excerpt]

    Thanks a MILLION for this information, I finally was able to solve the problem of running out of desktop heap (of course I didn’t know that was the cause until I read this post)!  For the last 10 years, I have been running a mix of mostly NT4 (and some Win2K) and I run my workstation for approx 3-6 months at a time between reboots, and typically 50 windows open on the task bar.  Nothing I searched for could solve this problem…

    With your help in this article, I loaded dheapmon and found that every time my malfunction occurs, I’m at 99.9% desktop heap usage.  I increased my Desktop Heap from 3072 to 4096 and it has solved my problems….

    From this eccentric power user… I give you a thousand thanks!

    Josh Straub

  22. Larry says:

    [Moderator’s note: The following is an excerpt]

    2 questions, Is there any way to map the winstation name back to the domain account that is running the service? And is a reboot required for changes to the non-interactive heap to take effect?

  23. ntdebug says:


    The windowstation names that are of the form “Service-0x0-xxx$” are based on the LUID for the logged on user.  I’m not aware of a way to map that value back to a name for a domain user.  Although several local accounts have static LUID values, as defined in the Platform SDK in winnt.h…

    #define SYSTEM_LUID                     { 0x3E7, 0x0 }

    #define ANONYMOUS_LOGON_LUID            { 0x3e6, 0x0 }

    #define LOCALSERVICE_LUID               { 0x3e5, 0x0 }

    #define NETWORKSERVICE_LUID             { 0x3e4, 0x0 }

    To answer your other question: yes, a reboot is required for changes to the size of the desktop heaps (the SharedSection settings) to take effect.

  24. Lev says:

    Hi we have similar problem on one of our client machines. With default settings for SharedSection=1024,3072,512. When we get out of memory we are at 96.5% heap usage. If we increase Desktop Heap size by 512, do we have to reduce the other numbers?

    Thank you for the answer

  25. ntdebug says:

    Lev – If you increase the size of any of these values, you will use more session view space.  Typically an increase of 512KB won’t require any additional tweaking.  I’m not sure if you are planning on increase the interactive desktop heap size (second parameter) or the non-interactive desktop heap size (third parameter).  Increasing the non-interactive heap size often has a larger impact overall, since for session 0 there are multiple non-interactive desktops, and each one will increase in size.  On a typical client machine I wouldn’t expect an increase of 512KB to either the second or third value to be problematic.

  26. Richard says:


    This is a great article and it makes things much clearer.  You state this is all true when not running with the /3Gb switch.  I notice that regardless what the setting is in the HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerSubSystems, when enabling the /sBd switch the heapsize for Service-0x0-3e7$Default is limited to 128.  When I remove the 3 Gb switch it goes to the set value 2048.  At some instances we are required to run the 3Gb switch as we are running a large database and we hit the 2Gb limit.  Is this value of 128 "tunable" at all?

    Thanks again for this great article,


  27. Jason says:

    For you guys who have messed with the "desktop heap" settings….

    I need you help. I generally have about 20+ windows open on my XP system, which has 1 gig of ram in it.

    I changed the middle setting for the desktop heap, following the info from here: [url][/url]

    This has helped, but now it seems I’m starting to have the same problem again, (not being able to open any new programs or windows, when I have 20+ open already).

    1) Can you tell me what is the best setting for me? What is the max I can go on the heap? This system is used by only one person, me.

    2) What should have my Virtual memory settings at? I have it at 500min/500 max, right now.

    I just want to be able to open more windows

  28. Mark says:

    Thanks for this great article!  Could there be other causes for this problem of services failing to start and returning the 0xc0000142?  It could be I am missing something but the output from the dheapmon tool on a Windows 2000 system with this problem does not seem to reveal a problem.  Am I missing something?

    C:kktoolsdheapmon8.1×86>dheapmon -l

    Desktop Heap Information Monitor Tool (Version 8.1.2925.0)

    Copyright (c) Microsoft Corporation.  All rights reserved.

     Dheapmon – Driver loaded successfully


    Desktop Heap Information Monitor Tool (Version 8.1.2925.0)

    Copyright (c) Microsoft Corporation.  All rights reserved.


     Session ID:    0 Total Desktop: (  7296 KB –    6 desktops)

     WinStationDesktop            Heap Size(KB)    Used Rate(%)


     WinSta0Default                    3072             10.5

     WinSta0Winlogon                    128              4.0

     Service-0x0-3e7$Default           1024              9.9

     SAWinStaSADesktop                 1024              0.2

     Service-0x0-15337$Default         1024              0.6

     Service-0x0-16c98$Default         1024              0.6



  29. ntdebug says:


    I’m glad you found the article helpful.  The behavior you are seeing with 3GB is the result of the following:

    1. When booting non-3GB, the size of session view space is controlled by the SessionViewSize registry value.

    2. When 3GB is enabled, the size of session view space is fixed at 20MB.  This is likely smaller than the value specified in the SessionViewSize registry value.

    3. During the initialization of the window manager, an attempt is made to reserve enough session view space to accommodate the expected number of desktops heaps for a given session.  The size of each heap is calculated using the registry values from the SharedSection string.

    4. If this attempt fails, then the window manager falls  back to a pair of “safe” sizes for desktop heaps (512KB for interactive, 128KB for non-interactive) and tries to reserve session space again, using these smaller numbers.  This ensures that even if the registry values are too large for the session view space size, the system will still be able to boot.

    In your scenario, the smaller desktop heap size is used because (a) 3GB requires that the size of session view space is smaller than normal, and (b) the smaller size of session view space cannot accommodate the larger non-interactive desktop heaps.  That is to say, the window manager doesn’t totally ignore the SharedSection registry string, it evaluates it in context of the size of session view space and the specified desktop heap sizes.  When you run into this problem, the 128KB value is fixed, because it is last-resort option that is used to make sure the system boots.  However, you may be able to reduce the 2048 value to something less, and still get larger desktop heaps, even while running 3GB.

  30. ntdebug says:


    I suggest you use dheapmon to verify if you are running into a desktop heap problem or some other problem.  The maximum interactive desktop heap size that you can use depends on the size of session view space on your system and how fully session view space is utilized by other allocations (non-interactive desktop heaps, GDI allocs, etc).  As far as virtual memory goes, a general rule of thumb is set your page file size to 150% of your physical memory.

  31. ntdebug says:


    Yes, there are many reasons that a process may fail to start with a 0xc0000142.  That error code is defined as STATUS_DLL_INIT_FAILED in the Platform SDK.  It means that a DLL did not initialize successfully.  This happens when a DLL returns FALSE from DllMain during DLL_PROCESS_ATTACH.  This could be due to failure in any DLL that the process loads during process initialization.   “Loader snaps” may help you isolate this problem further.

  32. Ciro Ettorre says:


    I have a similar problem on my computer. When logging in with a particular account ( my account on our domain, ex: domain/ciro ), I rapidly exhaust all the GDI/USER resource ( not being able to launch any application ) after opening let’s say 7-8 Internet Explorer sessions.

    Now, logging in with a different account on the SAME machine ( ex: myMachineciro ), I can open tenth of IE sessions and starting ANY application without problems.

    I monitored both accounts with dheapmon and apparently EVERYTHING is similar. Where can I look for further investigations ?



  33. BarfieldMV says:

    Now this makes me curious. If I just create a program that opens a small window with some simple controll in a endless loop. How fast will i get this exception? (after about 50 screens vista turns off a Color scheme -> 250 screens later I started to get too bored and afraid of a system crash)

  34. Edward Grigson says:

    Does this apply to Windows 2003? We have software written by a third party and they’ve told us that this only applies to Windows 2000. I’m in the process of creating a standard OS image so I’d want to include the changes if it does apply.

    On Windows 2000 we change the non-interactive heap settings to 2048 (from the default of 512).



  35. ntdebug says:


    If dheapmon does not show that desktop heap is exhausted, then it sounds like your domain account is experiencing some other problem.  As a starting point, you could start with Process Explorer -> System Information and check other system resources.  You can also use LiveKD and run !vm to check out virtual memory usage.

  36. ntdebug says:


    The scenario you described is going to eventually consume all the desktop heap for the interactive default desktop for the session you are in.  The time to failure will vary based on what else is creating USER resources in that desktop heap.  You can use dheapmon (on Server 2003 and earlier) to get a feel for how close you are to exhausting the heap.  The time to failure will also vary based on the OS version and platform, since the size of USER objects will vary somewhat, and due to the different heap sizes on 64-bit Windows.

  37. ntdebug says:


    Yes, the SharedSection registry values are applicable on Windows Server 2003, as long as you are not booting with 3GB.  Keep in mind that by setting the non-interactive heap size to 2MB, you will be creating multiple heaps which are all 4 times larger than usual.  I would recommend running dheapmon with this configuration to see how many non-interactive heaps you have under normal load, to ensure that you have some room to grow in session view space.  

  38. Matthew here again – I want to provide some follow-up information on desktop heap . In the first post

  39. Matthew, thanks for these great articles – definitely something that better be published on MSDN as well.

    However, I would like to add that “services” could mean out-of-process COM server as well, right?

    I remember we had some problems in that space some time ago, after XP SP2 came out (!2E073207A544E12!162.entry).

    I also would like to advice that changes to the SessionManager registry entries may prevent a system from booting, so everybody be extra-careful when touching these on production systems and have a recovery strategy established and tested.

    [Good point. The heap size for non-interactive desktops applies to any process running in a non-interactive windowstation, not just services. This certainly can apply to out-of-process COM servers. – Matthew]
  40. Bert's blog says:

    If you would like to resolve GDI and USER handle issues I would recommend reading: The HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSubSystemsWin

  41. Neal says:

    So what’s changed with Vista? On my Vista system I cannot run anywhere near the number of programs as I could with XP.I’ve also doubled the memory to from 1 to 2GB, with out any imporvement.

    What gives?

  42. Si no considero las 3 horas que dormí del viernes al sábado, podría decir que llevo casi 48 horas despierto, o que llevaba hasta hoy en la mañana ya que pude dormir 5 horas más de 6 a 11 am (hoy es domingo en la tarde). ¿Cómo tanto?. La primera trasnochada

  43. Yousef says:

    Well, Have any one figured out a solution yet for Windows Vista? There doesn’t seem to be a “Windows” section under the registry Key

    HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSubSystemsWindows

    For Vista…

    But yet there seems to be a resource limit of some sort in Vista as well. Could this be under another key? I have Vista Ultimate installed.


    [“Windows” in this context is a registry value, not a registry key. It should be there on Vista too, as a REG_EXPAND_SZ. – Matthew]
  44. Stanley Siu says:

    This reflects the chanllenges that Microsoft aces is that the Windows is used by wide spectrum of hardwares, from very little memory to gigs of memory. So it is hard to find a good default value.

    How about making it adjustable in Control Panel?

    Although it seems too dangerous for general user.

    How about putting it in the unsupported tool like PowerToy for XP/Vista?

    How about doing self-tuning in the installation step in both OEM and consumer version?

  45. Chris Quirke says:

    Shades of 16-bit heaps in Win3.x, isn’t it?  This certainly fits what I see in IE7 on XP SP2.  So why do these heaps not dynamically expand, after the lessons of Win3.x and 9x?

  46. Philippe Verdy says:

    Why a process, that creates a desktop in its session using CreateDektopEx(), cannot specify (or tweak) the Desktop Heap size it really needs?

    Isn’t there some envisioned improvement (notably for most services that don’t need any service from the desktop), so that the default non-interative dektop heaps would be reduced by default, and increased only on demand by the specific services that need it?

    Note that the session manager could look at the prefered desktop heap size within a registry entry associated to the service that performs the CreateDektopEx() call, even if the code of this service is not modified. This would change very simply the effective default desktop heap size used by those non-interactive services, and it would still allow specific installations of Windows to be tuned by just adding or changing such registry entry for the service (whose absence would mean that the third parameter, specified in the registry for the settings of the session manager, would be used as it is today).

    Finally, changing at run-time the desktop heap size should be possible by performing an IoControl request to the handle associated to the desktop; this would not necessarily require a new API, just a new IoControl request type, which may remain specific to the current version of Windows, and that should be secured using the user priviledges associated to the calling process, according to the user account owning the session object).

    An optional helper API could be created on top of this IoControl, using a new modelized and standardized API similar to ToolHelp;

    it could also be done by extending it to cover the administration of desktop heaps, including the possibility to include them in the list of other Ressource Monitor collectors, at least in read-only mode, so that desktop heap resource exhaustion can be more easily diagnosed; here also, no additional API is required in Windows, and we could use the standard "Performance Analysis tool" (in the existing collection of Administrative tools) to query the current status of Desktop Heap and Session objects: just assign them with a Performance object name.

    Such Performance helper DLL should also be made available to Windows XP (based on your existing advanced debugging tool described above) even if it does not allow an application to control the Desktop Heap sizes or the Session pool size at run time.

  47. Philippe Verdy says:

    Now that Vista features the LUA isolation mechanism that creates additional sesion objects and isolates the interactive services from other interactive user applications, it should be good to describe how the various sessions and desktops are shared, isolated, or tweakable in Vista.

    And isn’t there an additional desktop used by the LUA alerts that are displayed on top of the current desktop with a transparent greyed effect, when LUA is enabled in Vista’s session manager?

    [UAC uses the per-session winlogon desktop (also known as the secure desktop) to display prompts. The “transparent greyed effect” is basically a bitmap of what the user’s desktop looked like at the time of the prompt. – Matthew]
  48. Pepper says:

    This sounds suspiciously like it might be the cause of a problem I’m having with some Win2003 webservers. They run a lot of asp code under several application pools. Sometimes the ASP code fails simply saying “out of memory” and the only way to get it working again is to recycle the pool. Any advice?

    [This is probably not a desktop heap issue. You can run dheapmon and check desktop heap usage at the time of the problem to check. – Matthew]
  49. Rick says:

    I can’t thank you enough for posting this information.  This article helped me suggest a workaround for a serious customer problem that I never would have figured out otherwise.

    Our application runs as a Service, and its purpose is to start a number of other (non-service) processes (maybe 30 or 40) that make up our system.  It works fine, except on Windows XP SP2 systems, where, after successfully starting 20-25 processes, any additional processes it creates die immediately with the 0xC0000142 error.  I could never figure out why until I read this article.  By changing “SharedSection=1024,3072,512” to be “1024,3072,256”, the behavior changed so that I could only run 8 processes at once.  Changing the 512 to be 1024 allows the application to start at least 40 processes without any problem.  So, I know I am on the right track.

    However, I still have a couple of questions.  None of the processes that are started by this service interact with the desktop at all.  So, I am wondering if I can change the way our service creates these processes such that they are not affected by the Desktop Heap limitations at all.  The service itself gets created with the SERVICE_WIN32_OWN_PROCESS flag, and then it calls CreateProcess for each process.  I have played with the CREATE_NEW_PROCESS_GROUP and DETACHED_PROCESS flags, and found that using the DETACHED_PROCESS flag allows the service to create about 7 or 8 more processes then without it, but still limited.  Also, if I run my service process interactively, it ALWAYS starts ALL the processes without any problem.

    Is there any way for a service to create backgound processes that are not subject to the Desktop Heap limitation?

    [All process that load user32.dll use desktop heap, and all such processes are subject to desktop heap size limits. In your case, it sounds like your service is starting multiple processes that share a non-interactive desktop. These processes will also share a desktop heap. By running your service interactively, your service will use the 3072 KB interactive desktop heap instead of a 512 KB non-interactive heap. If you want to run the service non-interactively, then it sounds like increasing the 3rd SharedSection was a good choice. The only way to prevent desktop heap from being used at all is to not load user32.dll at all (which is often not an option). – Matthew]
  50. Andy says:


     Great article, I was struggling to find any info on this!

    I have a Windows Server 2K3 running Exchange 2003. I occasionally get the system event log error “Failed to create a desktop due to desktop heap exhaustion”

    I originally changed the settings detailed here –

    This has not fixed the problem, at present my SharedSection settings are default, would I want to change the second or third setting, what would be recommended.

    Many Thanks


    [“Failed to create a desktop due to desktop heap exhaustion.” is logged when the heap itself cannot be created. If a desktop heap cannot be created, then the entire desktop creation attempt fails. Usually a failure to create a new desktop heap means that session view space is exhausted for the session. You may be able to resolve this issue by increasing the size of session view space (using the SessionViewSize registry value) or by decreasing the third shared section value (assuming session view space is primarily used by non-interactive desktop heaps), to allow for more heaps to be created. Before making any changes, I suggest you use dheapmon to view desktop heap usage on your system shortly after you see the error. It helps to understand the usage of desktop heap before making changes. FYI, the desktop heap failure errors are only logged once per session to avoid a flood of events in the event log. So you may actually have more than one failure per session, but only one is logged. Desktop heap logging can be enabled or disabled with the DesktopHeapLogging registry value (see KB 810807). – Matthew]
  51. km says:

    How would I determine if the box has hotfix 318942 installed?

    [318942 contained a kernel binary (ntoskrnl.exe, ntkrnlmp.exe, etc) with a version of 5.0.2195.6797. Make sure that the kernel you are running is 5.0.2195.6797 or later. – Matthew]
  52. vmaystro says:


    This is a great article – thank you. I know now how to change the heap size manually in the Registry. Now I would like to detect programmatically if there is not enough heap space when my program starts. Are there any Windows API calls to do this?

    Thank you.

    [The size and usage of the desktop heaps are not obtainable using Windows API functions. Desktop heaps are a resource that only USER accesses directly (via its kernel mode implementation in win32k.sys), and would usually be considered an internal implementation detail of USER. Consequently, Win32 doesn’t expose many functions for directly dealing with desktop heap. Beginning with Vista, there a couple of exceptions: GetUserObjectInformation and be used with UOI_HEAPSIZE to get the heap size (but not the usage), and CreateDesktopEx can be used to specify a new heap size. – Matthew]
  53. dr says:

    Does LUID “Service-0x0-3e7$Default” represent all the services that run as LocalSystem?  If not, is there a way to map that back to a specific Windows service?


    [Yes, the service processes that run under local system will run under the Service-0x0-3e7$ window station. By default, the “Default” desktop will be used by threads in this process, but other desktops could be created and used. – Matthew]
  54. Oliver says:

    Matthew – great article, many thanks!

    We have a Windows 2003 Terminal Server SP2, with 4GB Physical RAM and using the following boot.ini switches:

    /noexecute=optout /fastdetect /3GB /PAE /USERVA:3030

    The server hosts about 10-15 terminal clients. There is a CRM client (Amtangee) installed which queries a separate Amtangee SQL Server.

    Users complain that if they open several faxes at the same time within Amtangee, they get a warning error along the lines of “…not enough memory storage is available to process this command”. The client then crashes. Only after a logout/login does the client app work again, until several faxes are opened…

    We spoke with Amtangee and they believe it’s to do with GDI-Handles. We have experimented with different settings but still have the same problem. Registry keys changed are:

    GDIProcessHandleQuota 65536

    UserProcessHandleQuota 65536

    LargeSystemCache 1

    DisablePagingExecuive 1

    PagedPoolSize 0

    NonPagedPoolSize 0

    SharedSection 1024,4096,512

    I have read your article with interest. What I would appreciate are you thoughts of what switches are best to use for boot.ini along with memory management, sessions & desktop heaps and any other optimisation tips for our terminal server.

    I really look forward to your comments. Many thanks, Oliver

    [Troubleshooting at this complexity and making specific configuration recommendations is beyond the scope of this blog, but I’d be glad to give some thoughts. It sounds like Amtangee is throwing ERROR_NOT_ENOUGH_MEMORY which is “Not enough storage is available to process this command.” This is fairly generic error, and it may be that a Windows function is returning it to Amtangee, and they are in turn displaying it to the user. Or it may be that Amtangee hit a failure within their code, and this is just the error they chose to return. In either case, it would be worth investigating if Amtangee can tell you if exactly what condition led to the return of this error. That would be a good starting point to determine what resource may be exhausted. Since Amtangee has already referenced GDI handles a possible problem, I suggest you pull up task manager while in state and see what the GDI Object count is for each process in the session. See if any process has an excessive GDI count, or if the total GDI handle count for the session is excessive. If the problem only affects one session at a time, then the resource is not going to be a system wide resource like page pool. You could be running out of session view space or session paged pool. You could also verify desktop heap usage using dheapmon. – Matthew]
  55. Paulette says:


    Great article! But I don’t know if desktop heap is what I’m facing. I have a problem with some applications running or my computer. When I launch some applications they come up with blank(white) screens. An example is starting up Windows Help & Support, the right window is always blank regardless of what I click. Same goes for my MS Project, I get a plain white page. Most applications give me a plain white page or just an empty page.

    I’m really not sure what the problem is. What do you think? I would appreciate some help here.

    Thank you.

    [I would suggest you start by using dheapmon to see if you are indeed exhausting desktop heap. – Matthew]
  56. Greg says:

    We’re facing precisely this problem. But I don’t know where to go from here. Telling users to raise SharedSection and reboot just isn’t the solution. We need to figure out where we’re allocating these desktop objects. dheapmon seems to give the bottom-line numbers but no detail.

    How can I find out what objects are being allocated in the desktop heap? And preferably which dll is actually causing them to be allocated?

    Is there some convenient function I can set a breakpoint on and catch each time user32.dll actually allocates memory from it? Then I could look at the backtrace and see what’s going on. Or some magic options to dheapmon to get more useful detail? Or something equivalent to ltrace/strace/ktrace which will let me see what what’s going on?


    [Assuming an individual desktop heap is exhausted (as opposed to an exhausted SessionViewSpace),  I recommend you start by looking at the USER object count in task manager. That will at least tell you what process is the likely primary consumer of desktop heap. If you stop the process in question, you should see desktop heap usage drop in dheapmon.  (You may have already narrowed things down this far, but I’m covering my bases here).  Once you know what process is using the heap, you’ll need to determine what kind of USER objects are being allocated by the process.  Not all USER objects come out of desktop heap, but windows, menus, and hooks do.   In most cases, it is window objects that are consuming the heap, as they are commonly used.  Setting a breakpoint on USER32!NtUserCreateWindowEx will allow you to catch the process creating windows, and see if anything looks out of the ordinary (this breakpoint may be hit often).  You could also use SPY++ to look for an excessive number of hidden windows that you wouldn’t be able to observe without SPY++ or the debugger.   – Matthew]
  57. Rick says:

    Paulette, when even Task Manager comes up empty, I know it is time to reboot.

    Another symptom is pulldown menus with missing items.  Sometimes a pulldown would show the separators, but none of the real items.

    I have had this since NT days, when I had trouble keeping NT up for more than a couple of days.  Now, with 2000 and XP, it is more like a week.  I do keep dozens of windows open.  For example, I am quick to open Outlook emails, but slow to close them.

    One thing that often pushes Windows over the breaking point — opening any of the Office apps.  It is as if they slam the Heap (or whatever) more than most apps.

  58. Greg says:

    Thanks a lot, Matthew. I guess I didn’t give enough context though. This is our own software I’m talking about. I can see clearly that each spawned process was taking up just over 9k of Desktop space which out of 512kb goes quickly. This is a non-interactive server daemon so it isn’t creating any windows and really doesn’t have any business using any Desktop Heap allocations. On unix we handle thousands of processes just fine so ideally we would want to consume 0 Desktop Heap on windows since we really don’t need it and want to scale just as well.

    The problem isn’t that our code is creating windows or any other GUI elements. The problem is that some DLLs we load are allocating space from the Desktop Heap when they’re initialized.

    We’ve already tracked down 6k of the 9k by removing calls to wsprintf and SHGetFolderPath. I can’t imagine why either of these should need 6k of space per process in a shared memory segment but presumably they come from DLLs that are initializing some unrelated data structures for future use. We’ve replaced them with our own snprintf and using the APPDATA environment variable.

    Now the problem is that we’re still allocating 3k of Desktop Heap and that’s still limiting how many processes we can spawn. I’ll try a breakpoint on CreateWindowEx like you suggest but I suspect it’s not hidden windows but something more obscure. Surely all the clients of the Destop Heap including CreateWindowEx call some common memory management function to actually allocate space from it? If I could set a breakpoint there that would be ideal.

    [Thanks for the clarification. Let me give a little background on how desktop heap allocations are made. The desktop heaps are in kernel mode virtual address space, so individual desktop heap allocations have to be made by a component running in kernel mode. In particular, win32k.sys is the only kernel mode component that makes desktop heap allocations. win32k.sys in the kernel mode side of Win32, and it includes both the window manager (USER) and GDI. It is the window manager piece of win32k.sys that uses desktop heap. The functionality of the window manager is exposed to processes running in user mode through user32.dll. It is user32.dll that exports user mode callable functions that are implemented in win32k.sys. So if a process does not load user32.dll, it will not use desktop heap.

    Regarding your question about setting a breakpoint that will catch desktop heap allocations… yes, there is such a function – win32k!DesktopAlloc. However, this is a kernel mode function, and to set a breakpoint on it will require that you use a kernel debugger.

    Since your process is non-interactive and you do not create windows directly, it is worth considering what components your code relies on that may be creating windows on your behalf. If you app uses COM then these allocations could be from OLE STA thread windows. If you are building your app as a console subsystem application you may want to consider building it as a windows subsystem app instead to avoid the auto creation of the console window. No windows are created automatically for windows subsystem apps. – Matthew]

  59. Just had a server totally stall after doing a reboot to apply the latest patches.

    During the first restart got the event id 244

    “Failed to create a desktop due to desktop heap exhaustion.” About four hours after this, the server just stopped responding. Did a reset and it came up OK with no errors, but nothing else in the log.

    My questions are:

    Could a problem with the desktop heap cause the server to stop responding (not even to ping!)?

    What could have caused this problem in the first place.

    [Desktop heap allocation failures alone won’t lead to a complete server hang. The underlying reason for the hang is hard to guess based on the limited information we have. If you see this problem continue to happen you could force a memory dump of the system when it hangs (see KB 244139) and work with Microsoft support to have the dump analyzed.]
  60. Jennie says:

    A very informative article, thank you. Can you tell me what are the “allowed” values for the non-interactive desktop heap? We are having problems with 1024 (failure to create a new process at a certain point in one of our applications), but 2048 is too much (some services don’t start). Is it OK to use a number in between these values, or must it be a power of 2?

    [You can use a size that is between 1024 and 2048. The value that specify will be internally rounded up to a multiple of the page size (4KB on x86).]
  61. eucaly61 says:

    I found myself might suffer from the resource leak with IE7, ever found the GDI of IE7 grew up to 3xxx (and total system 93xx). I tweak the heap from 3072 to 8192, and both GDIProcessHandleQuota, USERProcessHandleQuota to 15000(Dec). While still could not help. Now I stop use IE7 and try to monitor by taskmgr.exe But I got confused because there are three columns GDI, USER, Handles …

    (1) are GDI/USER limited by GDI/USERProcessHandleQuota ?

    (2) what’s the meaning of Handles in taskmgr.exe as compared to GDI/USERProcessHandleQuota …

    [GDIProcessHandleQuota and USERProcessHandleQuota are used to set per-process limits for GDI objects and USER objects, respectively. This caps the number of objects that a single process can use. The “handles” column in task manager refers to handles to kernel objects, rather than handles to USER or GDI objects.]
  62. TechNew says:

    C:kktoolsdheapmon8.1×86>dheapmon -s

    Desktop Heap Information Monitor Tool (Version 8.1.2925.0)

    Copyright (c) Microsoft Corporation.  All rights reserved.


     Session ID:    0 Total Desktop: (  5312 KB –    7 desktops)

     WinStationDesktop            Heap Size(KB)    Used Rate(%)


     WinSta0Default                    3072             10.4

     WinSta0Disconnect                   64              4.5

     WinSta0Winlogon                    128              8.8

     Service-0x0-3e7$Default            512             23.8

     Service-0x0-3e4$Default            512              4.3

     Service-0x0-3e5$Default            512              2.4

     SAWinStaSADesktop                  512              0.5



    This is the output I am getting after running Dheapmon on a particular PC.

    If you notice it only says 7 desktops insteas of 8.

    Could you give me any possible reason why this would be.


    [The number of desktops in a given session will vary based on what is running in that session. This isn’t unusual.]
  63. Jon Galloway says:

    Summary Opening too many tabs in Internet Explorer 7 can cause the Windows shell to switch to "Evil Mode

  64. Xavier says:

    We have a Windows 2003 St, x64 with heap memory problems. Microsoft support recommended increasing the value to SharedSection=1024,20480,2048 and after 2 or 3 weeks the heap gets full. this is what we get from the dheapmon tool. Could someone help with this?

    Desktop Heap Information Monitor Tool (Version 9.0.3040.0)

    Copyright (c) Microsoft Corporation.  All rights reserved.


     Session ID:    0 Total Desktop: ( 51488 KB –    9 desktops)

     WinStationDesktop            Heap Size(KB)    Used Rate(%)


     WinSta0Screen-saver              20480              0.1

     WinSta0Default                   20480              0.2

     WinSta0Disconnect                   96              5.0

     WinSta0Winlogon                    192              8.9

     Service-0x0-3e7$Default           2048              5.1

     Service-0x0-3e4$Default           2048              0.9

     Service-0x0-3e5$Default           2048              0.2

     SAWinStaSADesktop                 2048             96.1

     __X78B95_89_IW__A8D9S1_42_ID      2048              0.2


    [Based on the output you provided, the SADesktop is the desktop with an exhausted heap. This desktop is used by processes launched by the Task Scheduler service. My guess would be that your server has a scheduled task that runs regularly, allocates USER objects (and thus desktop heap), and isn’t terminating, so the desktop heap is never freed. You can check to see if there are any scheduled tasks that are hanging around for longer than expected. It may help to look for processes with an open handle to the SAWinSta windowstation. You can do this by running the following from session 0 “handle.exe -a SAWinSta”. ]
  65. MathCue says:

    Thanks for writing the definitive article on this subject.

    I’ve got a Server implemented as Service that spawns many subprocesses and runs into the 512K Desktop Heap limit, as verified via Dheapmon. All code is written in Delphi-5 and the host is running Win2000.

    I have tried setting up my subprocesses as console processes and creating with the DETACHED_CONSOLE and CREATE_NO_WINDOW flags. This  greatly reduces Desktop Heap consumption, but there is still about 3K allocated for each new process, and I would like to reduce this to zero.

    For testing, the subprocess is a minimal console app that does no real work. The only resources it’s allocating are a couple of Events to control the interprocess communication with the server. Do these events and handles perhaps get allocated from the D.H.?

    Could you shed some light on what still might be getting allocated from the Desktop Heap, and suggestions on how to eliminate the heap usage altogether?

    [If a process loads user32.dll, it will use desktop heap. If you want to completely eliminate desktop heap usage, you will need to remove any dependency on user32.dll. Regarding your question about events – object manager does not use desktop heap, so event objects and their corresponding handles should not affect desktop heap usage. Event objects are allocated from nonpaged pool.]
  66. David Fenton says:

    Thanks for the article.  I’ve recently been experiencing Desktop Heap issues in Windows Vista Ultimate (32-bit).  Context menu not appearing, can’t open more windows, can’t display task manager, etc.  

    However, I’ve been running into these problems even when running only 1-2 windows.  I have AIM open, as well as an anti-virus and firewall program in the background, but that’s all.  I have 2 GB RAM at ~50% utilization.  

    After a restart, I can open as many IE windows as I want (10+, although I typically only have 5-6).  However, after a short period of time, the Desktop Heap issue shows up.  As I close windows (typically 2), the problem fixes itself, but when I open another window, it reappears.  Each time I can open one less window, until I finally start seeing the problem after I have one window open (such as the one I’m typing in now).  

    I have no other windows open besides the task manager, but I can’t bring up a context menu in this IE window, and can’t open another window.  When it got to this point before, I was able to regain functionality by shutting down my graphics card control program (that had been running in the background), but the problem has re-occured (I never restarted the control program, so that wasn’t the cause).  

    Before a few days ago, I never had this problem (regardless of how many windows I had open).  I haven’t installed any new programs in the mean-time.  I know I can up the heap size, but I don’t want this problem to keep appearing.

    Do you know what could be causing this problem, or any way to find out?  I can’t check my heap usage because Dheapmon does not work for Vista, so I don’t know what I can do.  It seems like I’m just running out of heap space regardless of how many windows I close.  Is there any way some sort of leakage could be occuring?

    [Keep in mind that desktop heap allocations are for user interface objects. Assuming desktop heap is the limiting resource here, take a look at USER object count for each process running in your session and see if anything is using a large number of USER objects. Also, can you reproduce the issue in safe mode or using the msconfig diagnostic startup mode? If not, then you can use process of elimination to determine what is starting up in normal boot that leads to this problem.]
  67. MathCue says:

    Well, it seems that even for console apps, Delphi initialization apparently pre-loads user32 along with GDI32 and various other key components. We’ll probably need some user32 procedures anyway, so I guess we can live with that.

    Now the problem has become, how can our server running as a service get an interactive 3072K desktop heap?

    If we run the service under LocalSystem and check the “Interacts with desktop” box, I believe we’ll be assigned to WinSta0default. Is that correct? Once there we should be able to create another desktop and use that in our CreateProcess calls, thus getting all 3072K for our child processes.

    Another alternative would be to simply run our server as an ordinary interactive app and not as a service, but we’d prefer to keep it as a service, if possible.

    However, we are currently running the service under a “power-user” userid, and are thus assigned a 512K non-interactive heap. We’ve tried a SetProcessWindowStation to WinSta0, but apparently that requires Admin privileges. Is there any way for a service started the way we are doing it to latch into an interactive station and get the bigger heap?

    The new Vista CreateDesktopEx function looks like it would solve the whole problem (would it?), but we’re stuck with Windows 2000 Pro for the time being.

    Thanks again.

    [Yes, the “interact with desktop” checkbox allows the service to run in the interactive window station, and the service could then create more interactive desktops if needed. I wouldn’t typically recommend trying to force your non-interactive service (or its child processes) to run in an interactive windowstation simply to take advantage of the larger heap size. In general, increasing the 512K heap size (and possibly SessionViewSize too) is a better solution, assuming you can increase them sufficiently for your needs. You’ve probably already considered this, but if your service could be re-architected to reduce the number of child processes (perhaps handling the tasks with worker threads instead), you could scale back the desktop heap usage requirements. You are right about CreateDesktopEx; that may be a future solution for you.]

  68. Malcolm says:

    When I leave my computer on for a few days, I tend to have problems which seemed to be related to the desktop heap.

    Is it possible that applications can cause leaks with this memory – leaks that don’t get dealt with when closing the process. I think our application might be causing some leaks.

    e.g. run program – no errors, close, run again, some errors, close, run again, errors even earlier, etc. To fix I then close other apps, or just logout then log in.

    (these errors are related to calls to GDI calls e.g. CreateCompatibleBitmap with the GetLastError returning ERROR_NOT_ENOUGH_MEMORY or similar)

    [Desktop heap allocations are for user interface objects, which should be cleaned up upon process termination. If GDI bitmap allocations are failing, then you are likely running out of session view space or session pool. !vm 4 in a kernel debugger will show you overall session pool usage. This could be the result of a GDI object leak (likely bitmaps).]

  69. Vapor Blog says:

    DeskTop Heap Exhaustion Ran into another mine field the other day – blew my foot right off before I could

  70. dallasite says:

    Great comments!!  I have a theoretical question:  If I wanted to create 1 WindowStation and 1 Desktop and 1 IE process for 100 users, how would I go about getting the screen DC for each IE instance, so I could take the screen shot, modify it, and send it?

    Basically, I’m trying to utilize a stream of screen shots from hidden desktops for a highly optimized terminal server type application.  I only want 1 user account controlling all the WindowStations, because I don’t want 100 instances of winlogon.exe in memory.  I can’t use Terminal services because I have to change the network protocol on the fly.

    Any ideas?  Regular screen capture code doesn’t work with a hidden windowstation..

  71. ot says:

    I have been constantly having a problem with IE7 not being able to open a browser window over the last 6 months, or applications not loading, and I would have to reboot to clear the problem.  All would be well for a couple of weeks then this scenario repeated.  Researching, I found the dheapmon tool and have been using it, lauching it from a winapp I wrote to make it convienient to use.  Now I could see the problem, with WinSta0/default going to 99% and freezing windows, sometimes flakyness occurring at 95%.  Closing all the browser windows lowered the percent but, it would slowly climb back up even with only 1 window open, requiring a reboot.  Over time I narrowed it down to a program I wrote or IE7.  But one day I rebooted, and within the day I ran out memory (err 7) as reported by my program, and I had plenty of physical memory and page and virtual available.  I looked at the desktop heap and it was already at 99%.  I immediately suspected IE7 since my program runnning for a weeks at a time never caused such an heap shortage so quickly, indicating a serious memory leak.  Mimicking my actions, I was able to reproduce the problem 100% with IE7 being the cause.   So here is how  >> with Dheapmon running, go to a site that has lots of jpgs to view, shown as thumbnails. Read the heap, open a jpg by clicking on a thumnail, configure IE7 so that it opens a new browser window, not a tab off the same window. Note the heap again, close the jpg window, read the heap, you will have noticed that it didn’t release all of the heap it used.  Repeat this process, the heap in use will start climbing with each opening and closing of the jpg windows, it seems especially hungry opening the same jpg that is already sitting in IE Content cache.  Perhaps you could persuade someone at MS to fix this bug!  Email me for any clarifications.

  72. Arnab Gupta says:

    This is an excellent excellent article. This helped a lot in fixing the multiple process issues that we faced in one of our products. We start processes from Java and found that even though system resources allow, we could only start a fixed number of processes. We were using the Java Process and Runtime.exec API at that point. We are now using JNI and starting the processes by creating a desktop (CreateDesktop) and then starting processes using CreateProcess from that desktop. This has fixed our problem.

    One small question: The solution I described above worked seamlessly on Windows XP and 2000. On one 2003 machine, I had to change the Application Server service’s “Log In As” to an administrative account to make the CreateProcess work (CreateDesktop worked fine). We are currently looking into this issue. Any pointers will be very helpful.

    Once again thanks for a great article.

    [I’m glad you found the article helpful. I suspect that the issue you are seeing due to tightening of ACLs in Server 2003. This article shows how to change the ACLs for a desktop – You also may need to use CreateProcessAsUser.]
  73. It seems Vista has a different desktop tree. WinObj on my Vista shows that Session0 doesn’t even have any window station. If so why does OpenWindowStation from the service return valid handle? And what actually handle does it return? Is it a handle of an active session window station or what?

    [ Vista actually still has the WinSta0 windowstation and the usual desktops (Default, Disconnect, Winlogon), even in session 0. WinObj should still show the windowstations for session 0 under the root WindowsWindowstations. ]
  74. William says:

    Thanks for this article, Matthew. Very informative.

    In the article, you say; –


    Size if no registry value configured

    Default registry value

    Windows 2000 *

    20 MB


    I have a W2K SP4 Server. It’s running Terminal Services in Remote Administration mode, and has a significant problem with the 0xC0000142 error. As it’s a Mail Server, it spawns a lot of smtp32 processes. Too mnay processes, and it dies.

    DHeapMon currently shows: –

    C:kktoolsdheapmon8.1×86>dheapmon.exe -s

    Desktop Heap Information Monitor Tool (Version 8.1.2925.0)

    Copyright (c) Microsoft Corporation.  All rights reserved.


     Session ID:    0 Total Desktop: (  3968 KB –    5 desktops)

     WinStationDesktop            Heap Size(KB)    Used Rate(%)


     WinSta0Default                    3072             20.5

     WinSta0Winlogon                    128              5.2

     Service-0x0-3e7$Default            256             59.1

     SAWinStaSADesktop                  256              1.5

     __X78B95_89_IW__A8D9S1_42_ID       256              0.9


    Service-0x0-3e7$Default is the guilty party, and the utilisation shows >99% when errors occur.

    My issue is this: The SessionViewSize and SessionPoolSize keys don’t appear in the Registry, only SessionImageSize.

    Can I add the missing DWORD keys, and will this help?

    [Support for the SessionViewSize and SessionPoolSize registry values was added in hotfix 318942 (ntoskrnl from Nov 25, 2003, version 5.0.2195.6797). That fix was then included in Update Rollup 1 for SP4. If you have a kernel that is of version listed above or later, you should have support for the SessionViewSize and SessionPoolSize registry values. If you add SessionViewSize and increase the size, that alone won’t affect the size of the heap for “Service-0x0-3e7$Default”. I find it interesting that it is set to 256KB, instead of the default 512KB. I suspect someone changed the SharedSection value on this server, maybe because session view space was becoming exhausted. In any case, if you need more space for that particular desktop, you’ll have to increase its size with the SharedSection value, and if that causes session view space to become over-utilized, you can increase SessionViewSize.]
  75. Hi all, The other day I had to troubleshoot an issue with a process that a specific Windows service was

  76. This is an interesting question I have to admit I had not thought to until we got a case from a customer

  77. Sunit Joshi says:

    I cold not get dheapmon to work on windows 2003 Ent x64 edition. I went to the x64 directory and did a dheapinst.exe and got this error – Win32k.sys symbol load error. Correct symbol required.

    Any thoughts…?

  78. Sunit Joshi says:

    If the service has the option “Allow service to interact with desktop” set: would that mean that it would use the SecondSharedSection value ?

    [Yes, enabling this option causes the service to run under the default interactive desktop, and the second SharedSection value controls the size of the interactive desktop heaps.]
  79. !analyze -v says:

    "이 문서는 blog 의 번역이며 원래의 자료가 통보 없이 변경될 수 있습니다. 이 자료는 법률적 보증이 없으며

  80. Bob K says:

    What about GetGuiResources() – is that of any value as an API to call to gather some of this information?

    [Yes, GetGuiResources with GR_USEROBJECTS can tell you the per-process USER object count. This is the same information that task manager exposes, but the API may be useful in situations where task manager isn’t an option. The process using the most USER objects is the likely primary consumer of desktop heap.]
  81. Bob K says:

    Thanks – we have told our C# and C++ programmers to use this within their apps to detect (at least make an educated guess) at leaks. Also, can we use UMDH at all for detecting desktop heap issues, or is that for regular memory heap (malloc-type) allocations only?

    [UMDH isn’t helpful for desktop heap. UMDH tracks heap usage within a process (in the usermode heap manager), but not in desktop heaps.]
  82. This is a fantastic article. What is the 4th parameter for SharedSection= used for? Is this not supported in Windows 2003 and what happens if it is set?

    [I’m glad you enjoyed the article.  That’s a good question you bring up.  See my previous response here:]
  83. Do What? says:

    Exchange Client Extensions are used in Outlook to extend the functionality of Outlook.  A developer

  84. I recently worked on an issue where the customer was getting this error message when attempting to export

  85. xuyibo says:

    i also get this famous 0xc0000142 error in windows 2000 server. when 0xc0000142 popup, using dheapmon, here is the output:

    Desktop:(Default) …:

    Desktop Heap 6291456

    Committed    1859584

    the problem is, Committed heap doesn’t grow even there are many heap (6291456 – 1859584).

    and using depends to profile, i found load user32.dll(after imm32.dll) failure.

    using windbg two-machine debug, bp LdrpInitializeProcess, also can get user32.dll load failed.

    i have install the lastest sp using windows update, still have enough memory, and cpu usage is very low. what cause this problem?

  86. Max says:


    Congrats for the great article!

    In the context of our system, we are using 8 virtual display drivers (rendering to shared memory files) and 3 physical displays.

    For this purpose we had to extend the session space size to 240 instead of regular 48.

    But still we observed randomly attaching/detaching display issues.

    Having understood the way windows attach/detach a monitor (virtual or not) we are now clueless when we randomly observe a file mapping error when all the displays are trying to be attached on the desktop.

    Could someone explain me how to monitor my session space, as the live kernel debugging does not give me enough information as well as diving into the complete dump of the system…

    I would really appreciate some help on this part.



  87. Jack says:

    Is there any way to flush the desktop cache ?

    reset it without restarting windows ?

    this would be ver convenient.

    [Desktop heap usage represents USER objects (windows, menus, etc). The window manager cannot remove these objects from the heap while they are in use. A way to reduce desktop heap usage is to terminate the processes that have allocated the objects, or for those processes to voluntarily reduce their USER object usage.]
  88. Marek Vokac says:

    Hi, I too found this a great article. My pet mystery is this: On a 2003 Server running a database replication app (interactive, not service), I get symptoms of heap exhaustion.

    Like – windows not repainted properly, fonts missing, tray icons floating all over the place. The app itself crashed and the eventlog contains one event – "Fatal Application Exit : System Object not created". The exhaustion problems persist until I log off and create a new TS session.

    But: dheapmon shows a maximum level of 13.5% usage on that interactive desktop. When freshly started, it’s at 4-5%, and it rises slowly, so it would seem that something is leaking. But crash at 13% ?   and, neither Task Manager nor any other tool I’ve found shows any leaks (USER object, GDI, Page Pool, nonpaged, Virtual memory, you name it).

    Do you have any ideas at all?  Are there other explanations besides desktop heap exhaustion that would fit the symptoms?

    best regards,


  89. lorraine says:

    not sure if this is my problem.  in vista home basic in ie after games i get ‘out of memory line 19’  or the number will change to a 4 digit .  clicking ok usually makes it go but next thing i do it comes back.  sometimes 2 or more before it quits?????  any suggestions?

  90. We’d like the thank everyone who attended the Windows NT Debugging Blog Live Chat two weeks ago. Here

  91. We’d like the thank everyone who attended the Windows NT Debugging Blog Live Chat two weeks ago. Here

  92. Sometimes customers open technical support cases because of this (apparently simple) issue: “System.Web.Services.

  93. test says:

    his was a great primer on a part of Windows memory management that is seldom covered. Thanks!

  94. Thomas says:

    Is there a possibility of describing how this works under Vista, and providing a Vista-compatible version of dheapmon?

    I often have up to 20 IE tabs open on Vista, and with a few other applications (eg Outlook, Excel, Word), I seem to be hitting some resource limit, as new windows often fail to be created (unless I close some old ones).

    [Thomas, thank you for your interest in this article.  Unfortunately we do not have a publicly available version of dheapmon for Windows Vista.  Most load based resource exhaustion issues are eliminated by using x64, this is the solution that most customers have adopted.]

  95. Bollimuntha says:


    Your explanation is excellent. You defined our problem in last but not suggested any solution. Can you please provide solution.

    If the services all run under another user account which logs on multiples times, each time acquiring a new LUID, there will be a new desktop heap created for every instance of the service, and session view space will eventually become exhausted.

    [The article suggests that such services may be poorly designed. You may be able to tune the size of each heap by modifying the SharedSection values.]

  96. Hi guys, is there any official way how to check desktop heap utilization on Win2k8 and above except running !dskheap? What we did is that we captured complete memory dump but the !dskheap extension seems to be not working. I'm getting output like this (x64 W2k8 SP2, Win32k.sys desktop heap events logged in the system event log):


    Error Reading rpdeskList from WINDOWSTATION @ fffffa800f1e9f60

    Failed counting Desktops for Winsta @fffffa800f1e9f60

    EnumDsktps failed on Winsta:  f1e9f60FillWinstaArray failed

    I have experienced this extension to fail many times in the past on different complete memory dumps from various OS versions. I have also tried older version of windbg/kd but it did not helped. Is there something that has to be enabled on the OS level on the system where you are suspecting desktop heap exhaustion or is it just a debugger bug?

    [Either the information the extension needs is paged out, or you are not in the context of a process that has session space.  Find a process in the session where you suspect desktop heap is exhausted (!process 0 0), and change the debugger context to that process (.process /p /r ProcessAddress).  If this doesn't work, is the memory at fffffa800f1e9f60 valid? (dq, !pte)]

  97. Does someone know of a tool that will visually present raw data structures, for example in windbg ? And you should be able to search some keywords say DPC or interrupt and it should list all the hits on those.

    [I'm not sure how this question relates to desktop heap.  The x and dt commands accept wildcards.  For example you can run "dt nt!*DPC*" to find functions and structures that include the string DPC.]

  98. Shawn Hickey says:

    I am running Windows Server 2003 SP 2 without the SessionViewSize registry value set.  I plan on adding SessionViewSize to the reg set to 48.  

    My question

    Can I tell what the total current Heap usage is across all sessions at a given time without running Dheapmon under each session?

    [There is no automated mechanism to run dheapmon for each session.  However, often it is only necessary to inspect the desktop heap usage for the session where you are experiencing an issue.]

  99. In order to spare some time and frustration of people trying to troubleshoot possible desktop heap exhaustion on W2k8 and W2k12, here are some hints:

    W2k8 (non-R2) and W2k12 – It is not possible to determine desktop heap utilization using !dskheap extension. The reason is that public win32k.sys symbols do not contain the relevant data structures. Private symbols are required, and therefore the only option is to open a case with Microsoft support so the engineers can take a look. Confirmed with MS support engineer.

    W2k8 R2 – it appears that public win32k.sys symbols contain the relevant data structures, therefore !dskheap works. You can use it either during live debug session (livekd works great without any downtime) or complete memory dump analysis.

    I expect the situation above to be true also for client OS versions (W2k8 – Vista, W2k8 R2 – 7 and W2k12 – 8), but I have not tested it.

    Although I would personally not recommend it, i need to mention that there is also an unofficial release of dheapmon out there on the internet which should work on W2k8 an above, however it is not from Microsoft. Dheapmon driver for that unofficial tool is not digitally signed and you need to boot the OS with disabled driver signature enforcement (from advanced startup options) in order to get it work. But think twice before you use the tool as it may cause stability and also possible security issues.

    [Hi Miroslav,

    You are correct, tagDESKTOP is not in the public symbols for Server 2012 and Windows 8. If you want to know why that matters to !dskheap, see our article at

    Desktop heap exhaustion was common in older platforms but is a very unusual issue in Windows Vista/Server 2008 and newer versions of Windows.  Because of improvements in the OS, !dskheap is not used as often on these platforms.

    Please think more than twice before disabling driver signing and installing software from the internet.  Microsoft does not recommend this practice.]

  100. Randy Reist, Software Engineer, Ret; Unisys says:

    This article desperately needs updating to reflect today's W7, 64-bit addressing technology!

    [As mentioned in the article, this architecture was changed starting in Windows Vista.  Desktop heap exhaustion is exceptionally rare in current versions of Windows, therefore we have not seen value in additional documentation.]

  101. Jason.Yang says:

    It help me resolve a big problem for launch many processes. Thanks very much!