{"id":23,"date":"2006-08-30T09:42:06","date_gmt":"2006-08-30T09:42:06","guid":{"rendered":"https:\/\/driverentry.com.br\/en\/2006\/08\/30\/exallocatepoolwithouttag\/"},"modified":"2026-07-24T17:10:49","modified_gmt":"2026-07-24T17:10:49","slug":"exallocatepoolwithouttag","status":"publish","type":"post","link":"https:\/\/driverentry.com.br\/en\/2006\/08\/30\/exallocatepoolwithouttag\/","title":{"rendered":"ExAllocatePool(WithoutTag)"},"content":{"rendered":"<div style=\"text-align: right;\"><a href=\"https:\/\/driverentry.com.br\/2006\/08\/30\/exallocatepoolwithouttag\/\"><img loading=\"lazy\" decoding=\"async\" title=\"Em Portugu\u00eas\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/br.gif\" alt=\"\" width=\"21\" height=\"19\" \/><\/a><\/div>\n<p>Like most driver developers, I also have to build drivers for various Windows versions. Although  I will not comment about VXDs on this post, I can comment about having a  single .SYS file that can run either in Windows Server 2003 and Windows NT. I  know that this OS is no longer sold and has no support  from Microsoft, but it is impressive to see how we still find Windows 95  and Windows NT both in corporate environments and in end  user&#8217;s homes. So, we always have to stay in dodging each operating system limitations when we are planning to develop a system.<\/p>\n<p>A  function that received a new version was <em>ExFreePool()<\/em>, its new version is  the <em>ExFreePoolWithTag()<\/em>, which is implemented since Windows 2000. To get a single binary that runs in both versions, we have to use the oldest one that still is supported by recent systems.<\/p>\n<p>Let&#8217;s consider the source below for a driver that performs the amazing task of allocating memory dynamically.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#include<\/span> <span style=\"color: #a31515;\">&lt;ntddk.h&gt;<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObject,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                     PUNICODE_STRING pusRegistryPath)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   PVOID pTemp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   <span style=\"color: green;\">\/\/-f--&gt; I'm thinking it's easy allocating memory.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">if<\/span> (!(pTemp = ExAllocatePool(NonPagedPool, 10))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">       <span style=\"color: blue;\">return<\/span> STATUS_NO_MEMORY;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   <span style=\"color: green;\">\/\/-f--&gt; Memory leak is vulgarity.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ExFreePool(pTemp);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   <span style=\"color: blue;\">return<\/span> STATUS_SUCCESS;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<p>Using  the build environment for Windows XP to compile this driver, we can see the same binary runs on Windows Server 2003, Windows XP, Windows  2000 and Windows NT. Or at least, it should. When we try to start our wonderful driver on a Windows NT, we get the following message:<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/erro001.png\" alt=\"\" \/><\/div>\n<p>But how? If we take a closer look at our driver, we find that it is a miserable traitor. As a DLL, drivers are executable modules that use the classical structure PE to declare their dependencies. Thus, we can open our driver in the <em>&#8220;Dependency Walker&#8221;<\/em> and see what it expects from life to be loaded. You may not believe, but it really statically depends on the new allocating memory function. A bastard traitor!<\/p>\n<div><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/depends001.png\" alt=\"\" \/><\/div>\n<p>This is because, within the file <strong>ntddk.h,<\/strong> there is a set of definitions that ends up changing the calls from <em>ExFreePool()<\/em> to\u00a0 <em>ExFreePoolWithTag()<\/em>. So,  we can get those tons of code written for NT and use them in  builds for newer systems without changing a single line, or we can  share some source between drivers for Windows NT and newer systems.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#define<\/span> POOL_TAGGING 1<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">...<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#ifdef<\/span> POOL_TAGGING<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: blue;\">#define<\/span> ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,<span style=\"color: #a31515;\">' kdD'<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#define<\/span> ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,<span style=\"color: #a31515;\">' kdD'<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: blue;\">#endif<\/span><\/pre>\n<\/div>\n<p>Then you ask me the following questions: But what is the real difference between old and new version? Can my driver experience problems if you try to use the old version running on a newer system? Is there intelligent life outside earth?<\/p>\n<p>The new version came to help detecting memory leaks. Each memory allocation is associated with a tag. These tags can be viewed using debugging tools such as WinDbg. For  example: If your entire library setup uses a tag, and its  communication library uses another, it will be easy to know which ones are  leaving allocated memory. This makes it easy to know which programmer on your team you will be fired. The macros in <em>ntddk.h<\/em> use only one tag to the default memory allocations which has no associated tags.<\/p>\n<p>But, what about drivers compiled with the DDK for Windows NT, running on newer systems? These drivers actually use the old functions. If we use <em>Depends<\/em> on them we could see that. As a matter of compatibility, the old functions are still exported in newer systems to support older drivers. Let&#8217;s take a look at the implementation of <em>ExAllocatePool()<\/em> Windows 2000.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/exallocatepool001.png\" alt=\"\" \/><\/div>\n<p>Implementation of the old function simply forwards the memory allocation for the new function and uses the tag <em>&#8216;None&#8217;<\/em>. This assures us that we will not die of cancer if we continue using old functions in a new system.<\/p>\n<p>Well, what were we intending to do? Oh yes, build a new driver that can run on both Windows NT and later systems. We could simply use the Windows NT DDK and have backward compatibility to run on newer systems. This is possible, but some of the functions we see in the DDK are actually defined as macros. The <em>IoSetCompletionRoutine()<\/em> function is a classic example of this. Using  an old DDK means not having some of these functions defined and we&#8217;d have to patch DDK definitions if we wanted to enjoy them. There are also those cases of missing people on desert islands with only the latest DDK.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#include<\/span> <span style=\"color: #a31515;\">&lt;ntddk.h&gt;<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#undef<\/span> ExAllocatePool<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: blue;\">#undef<\/span> ExFreePool<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObject,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                     PUNICODE_STRING pusRegistryPath)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">...<\/pre>\n<\/div>\n<p>To  resolve this, just after including <em>ntddk.h<\/em>, let&#8217;s take a <em>#undef<\/em> in macros that will redirect older calls to new version of <em>ExAllocatePool()<\/em> and that&#8217;s it, your problems have gone away. Rebuilding, we will have a new driver that uses the old allocation functions. Thus, it can be used in systems since Windows NT.<\/p>\n<p>This method disadvantage is that your drivers can not use the tags when running on a system that supports them. Actually,  you can have a single binary that, when running on Windows NT can use <em> ExFreePool(),<\/em> whereas when running on a newer system it uses <em>ExFreePoolWithTag()<\/em>, but  that&#8217;s another post.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Like most driver developers, I also have to build drivers for various Windows versions. Although I will not comment about VXDs on this post, I can comment about having a single .SYS file that can run either in Windows Server 2003 and Windows NT. I know that this OS is no longer sold and has [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-23","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/23","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/comments?post=23"}],"version-history":[{"count":1,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/23\/revisions"}],"predecessor-version":[{"id":24,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/23\/revisions\/24"}],"wp:attachment":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/media?parent=23"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/categories?post=23"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/tags?post=23"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}