{"id":147,"date":"2007-06-18T11:01:32","date_gmt":"2007-06-18T11:01:32","guid":{"rendered":"https:\/\/driverentry.com.br\/en\/2007\/06\/18\/we-want-samples\/"},"modified":"2026-07-25T16:05:21","modified_gmt":"2026-07-25T16:05:21","slug":"we-want-samples","status":"publish","type":"post","link":"https:\/\/driverentry.com.br\/en\/2007\/06\/18\/we-want-samples\/","title":{"rendered":"We want samples"},"content":{"rendered":"<div style=\"text-align: right;\"><a href=\"https:\/\/driverentry.com.br\/2007\/06\/18\/nos-queremos-exemplos\/\"><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><img decoding=\"async\" style=\"float: right; margin: 0px 10px;\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/SleepMeeting.png\" border=\"0\" alt=\"\" \/><\/p>\n<p>A few months after my hiring into <a href=\"http:\/\/www.opencs.com.br\/\">Open<\/a>, they asked me to do a participation in a lecture about <strong>Secure Code<\/strong>. My part was about stack overflow and how to take advantage of that oversight programmer to break into the program. The major point to note was in addition to programmers, the audience was composed by software engineers and architects, the commercial\u00a0staff, who had more contact with customers were there also, there were one or two people from administrative sector as well, in summary, an audience that few of them have heard about call stack. One of them said:<em> &#8220;I sort of remember from when I got my .Net certification, which said that structures are created on the heap and objects are created on the heap, or vice versa.&#8221;<\/em> Anyway, things became more complicated when I started to show the sample code I supplied, with PUSHs, MOVs and POPs. The result was: some slept, while others just drooled and spoke in that alien language while they sleep. I know that language very well because my wife always talks to me while she sleeps and I&#8217;m sitting in bed with the notebook. Despite her words being completely incomprehensible, she always responds when I make questions to her. She introduces the subject by saying: <em>&#8220;Admivoza bumizav&#8221;<\/em> then I ask: <em>&#8220;Why do you think so?&#8221;<\/em> And she replies: <em>&#8220;Zumirag abmish mua&#8221;<\/em>. But back to the subject, it became clear that the amount of technical detail was incompatible with the public. So, not long ago, in a talking about Windows drivers, I tried to pass a vision with little details, just to give an idea what drivers are and how they contribute to the system work. After all, the entire development department was there, including architects, engineers and .Net coders (nothing against them). To my surprise, at the end of the lecture, everyone was expecting more details, something like: \u00a0<em>&#8220;Hey, what about the remaining? Don&#8217;t you have any little example?&#8221;<\/em>. So, okay&#8230; In this post, I will write a minimal driver, but one that has some interaction with a test application.<\/p>\n<h3>At the beginning&#8230;<\/h3>\n<p>Here I will assume that you have already known <a href=\"https:\/\/driverentry.com.br\/en\/2006\/09\/11\/getting-started\/\">how to create a driver project from scratch<\/a> and <a href=\"https:\/\/driverentry.com.br\/en\/2006\/11\/16\/kernel-visual-studio-2005\/\">how to use Visual Studio to code drivers<\/a>, going straight to the point where we must write the driver. The today&#8217;s example will be a very basic\u00a0echo driver commands that will receive commands through reading and writing. So, it would be like that: you initially write buffers, which are strings in our example using the <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa365747.aspx\">WriteFile()<\/a> function and everything will be stored into the driver. The subsequent readings from the function <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa365467.aspx\">ReadFile()<\/a> will bring the same data from where were written. This example will be very useful in other posts, and will also serve as a starting point for those wanting to write their first driver.<\/p>\n<p>Knowing that we will store the strings in a list, and then we need to create a buffer\u00a0list composed by nodes defined as shown below.<\/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: green;\">\/\/-f--&gt; Type definition to be stored into<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      our buffer list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">typedef<\/span> <span style=\"color: blue;\">struct<\/span> _BUFFER_ENTRY<\/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;\">    PVOID       pBuffer;    <span style=\"color: green;\">\/\/-f--&gt; Sent buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ULONG       ulSize;     <span style=\"color: green;\">\/\/      Buffer size<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    LIST_ENTRY  Entry;      <span style=\"color: green;\">\/\/      List node<\/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;\">} BUFFER_ENTRY, *PBUFFER_ENTRY;<\/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;\"><span style=\"color: green;\">\/\/-f--&gt; List head and mutex for protection <\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">LIST_ENTRY      g_BufferList;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">KMUTEX          g_Mutex;<\/pre>\n<\/div>\n<p>After defining the structure, we have to create a global variable that will be the list head and also a <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa490233.aspx\">mutex<\/a>, to protect our list from possible accesses in parallel. This would happen if we had two test applications running at the same time. If you want more details about the DDK linked lists, there is a <a href=\"https:\/\/driverentry.com.br\/en\/2007\/02\/24\/linked-lists-on-ddk\/\">post<\/a> that explains about that, too.<\/p>\n<h3>Writing DriverEntry routine<\/h3>\n<p>The first point to notice here is that, since our example has been coded in a .CPP\u00a0file, it&#8217;s necessary to put an <strong>extern &#8220;C&#8221;<\/strong> at the <em>DriverEntry<\/em> function definition. Otherwise, the linker will not find the driver\u00a0entry point. Early in the implementation, we can see the message that will be launched to the debugger via <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms792792.aspx\">KdPrint()<\/a>. Next, I will initialize our linked list head and the mutex that protect it. Now let&#8217;s set some members in the <em>DriverObject<\/em> structure and the first will be DriverUnload\u00a0member, which receives a pointer to a callback function that will inform the driver that it is being unloaded. The next few members are the routines that will be called when the driver receives requests about <strong>Create<\/strong>\/<strong>Open<\/strong>, <strong>Close<\/strong>, <strong>Read<\/strong> and <strong>Write<\/strong>. I will talk about these routines with more details a little later. Continuing, the <em>DeviceObject<strong> <\/strong><span style=\"font-style: normal;\">is created<\/span><\/em>, which will be our way of communication way with the driver. As I said at the lecture, all requests a driver receives are through a device. <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa490468.aspx\">IoCreateDevice()<\/a> function makes this for us. Created the device, I will now configure it so that it should use intermediate buffers. For this, I have to set the bit <strong>DO_BUFFERED_IO <\/strong>in <em>Flags<\/em> field from <em>DeviceObject<\/em> you have just created. <strong>Intermediate buffers?<\/strong> We&#8217;ll talk about <em>BufferedIo<\/em> versus <em>DirectIo<\/em> in a future opportunity. There are so many new concepts in this post and I, unfortunately cannot go very deep into their details, otherwise nobody would read it that never seems ending up.<\/p>\n<p>Having a DeviceObject is cool, but it is not everything in driver&#8217;s life; for a <strong>User Mode<\/strong> application being able to communicate with a driver, you must create a <strong>Symbolic Link<\/strong>. This is done next with <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa490622.aspx\">IoCreateSymbolicLink()<\/a> function. The remaining function code should not cause great surprise to most of you, but if in doubt, just send me an e-mail and we can resolve this in a fight.<\/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: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     DriverEntry<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      This is the driver entry point.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      Knife in teeth and blood in eyes.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">*\/<\/span><\/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: blue;\">extern<\/span> <span style=\"color: #a31515;\">\"C\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                     IN 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;\">    NTSTATUS        nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PDEVICE_OBJECT  pDeviceObj = NULL;<\/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;\">__try<\/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: green;\">\/\/-f--&gt; Saying hello to the Kernel Debugger<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KdPrint((<span style=\"color: #a31515;\">\"Starting KernelEcho driver...\\n\"<\/span>));<\/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; Initializing the buffer head list and mutex<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        InitializeListHead(&amp;g_BufferList);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeInitializeMutex(&amp;g_Mutex, <span style=\"color: purple;\">0<\/span>);<\/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; Setting the driver unload callback<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pDriverObj-&gt;DriverUnload = OnDriverUnload;<\/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: green;\">\/\/-f--&gt; Setting the driver routines that<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      will be supported.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pDriverObj-&gt;MajorFunction[IRP_MJ_CREATE] = OnCreate;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pDriverObj-&gt;MajorFunction[IRP_MJ_CLOSE] = OnClose;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pDriverObj-&gt;MajorFunction[IRP_MJ_WRITE] = OnWrite;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pDriverObj-&gt;MajorFunction[IRP_MJ_READ] = OnRead;<\/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; Creating the control device<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = IoCreateDevice(pDriverObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                             <span style=\"color: purple;\">0<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                             &amp;g_usDeviceName,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                             FILE_DEVICE_UNKNOWN,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                             <span style=\"color: purple;\">0<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                             FALSE,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                             &amp;pDeviceObj);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            ExRaiseStatus(nts);<\/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: green;\">\/\/-f--&gt; Configuring I\/O using intermediary buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pDeviceObj-&gt;Flags |= DO_BUFFERED_IO;<\/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; Creating a symbolic link, so applications<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      can reach this device.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = IoCreateSymbolicLink(&amp;g_usSymbolicLink,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                   &amp;g_usDeviceName);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            ExRaiseStatus(nts);<\/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;\">    <span style=\"color: blue;\">__except<\/span>(EXCEPTION_EXECUTE_HANDLER)<\/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; Getting the error code<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = GetExceptionCode();<\/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: green;\">\/\/-f--&gt; That will force the debugger to stop here.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      But only when this code is built in Checked mode.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ASSERT(FALSE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KdPrint((<span style=\"color: #a31515;\">\"An exception occurred at \"<\/span> __FUNCTION__ <span style=\"color: #a31515;\">\"\\n\"<\/span>));<\/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; Since we had problems during the initialization, let's<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      undo what was done.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">if<\/span> (pDeviceObj)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            IoDeleteDevice(pDeviceObj);<\/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;\">    <span style=\"color: blue;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<h3>Writing Dispatch Functions<\/h3>\n<p>I&#8217;ll also assume that you have already had an idea of <a href=\"https:\/\/driverentry.com.br\/en\/2007\/02\/12\/cool-but-what-is-an-irp\/\">what an IRP is<\/a>.\u00a0Now let&#8217;s write the functions to manipulate them. They are called <strong>Dispatch Functions<\/strong>.\u00a0These functions are set at driver\u00a0startup time as you have seen in the code above. In the DriverObject structure, the MajorFunction\u00a0member is a function pointer\u00a0array indexed for macros like <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms806158.aspx\">IRP_MJ_READ<\/a>.\u00a0The function prototype is the same for all functions and it will be displayed below. <strong>Dispatch Function<\/strong> needs to handle IRPs following some rules, like everything else at DDK.\u00a0A minimal function could be written as follows:<\/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: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     OnDispatch<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      A minimum Dispatch Function example<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">*\/<\/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<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">OnDispatch(IN PDEVICE_OBJECT  pDeviceObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">           IN PIRP            pIrp)<\/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: green;\">\/\/-f--&gt; Here I fill the IRP status.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pIrp-&gt;IoStatus.Status = STATUS_SUCCESS;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    pIrp-&gt;IoStatus.Information = <span style=\"color: purple;\">0<\/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: green;\">\/\/-f--&gt; Completing the IRP. After that, touching the IRP structure<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      is absolutely prohibited. That does not belong to you anymore.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IoCompleteRequest(pIrp, IO_NO_INCREMENT);<\/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: green;\">\/\/-f--&gt; Return status code to the IoManager.<\/span><\/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><strong>But what if we had called the ReadFile() <\/strong><strong>function <\/strong><strong>with a handle to our device if we did not fill the position IRP_MJ_READ? Would we burn up forever in marble from hell?<\/strong> Indeed, if we take a look at <em>MajorFunction<\/em> table before filling it, we can see that there is the same address in all slots.\u00a0Let&#8217;s put a break-point at DriverEntry\u00a0entrance, take a look on the table slots before being filled out and see what&#8217;s there.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/NoFuncEcho.png\" alt=\"\" \/><\/div>\n<p>As we saw, this table is all initialized with a function pointer that it&#8217;s in implementation; considering that the power management IRPs have a special treatment, it completes the IRP with status <strong>STATUS_INVALID_DEVICE_REQUEST<\/strong>.<\/p>\n<p>A Dispatch Function basically follows one of the three alternatives for dealing with an IRP. In cases of filters, our driver could pass the IRP to the driver which it was attached to. Okay, that was noted here&#8230; &#8220;Do a post providing a filter example&#8221;. The second alternative would retain the IRP to an asynchronous processing and the last but not least, simply complete the IRP. Notice that in our example, all that we do is to tell the application that the IRP was successfully performed and completed it. To complete the IRP, we use the <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa490590.aspx\">IoCompleteRequest()<\/a> function, which receives the IRP to be completed and the <em>Priority Boost<\/em>. <strong>What?<\/strong> Assuming your IRP had some interaction with hardware, it would consume some thread time in Kernel Mode. This time it would create a delay in the current thread and this would be compensated by this <em>Boost<\/em>. Because this is not our case, we use the macro to define no Boost. DDK has a list of constants that determines the boost that a thread should receive for each type of device. See the WDM.h\u00a0excerpt (this definition may be in ntddk.h depending on your DDK version).<\/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: green;\">\/\/<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/ Priority increment for completing CD-ROM I\/O.  This is used by CD-ROM device<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/ and file system drivers when completing an IRP (IoCompleteRequest)<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/<\/span><\/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: blue;\">#define<\/span> IO_CD_ROM_INCREMENT             <span style=\"color: purple;\">1<\/span><\/pre>\n<\/div>\n<p>At the end of this post, there will be a link to download all the files needed to build the application and driver.\u00a0Notice, in the sample\u00a0sources, that our <em>OnCreate()<\/em> and <em>OnClose()<\/em> Dispatch Functions are too similar to the example above.\u00a0That&#8217;s because we don&#8217;t take no action when it opens or closes a handle to the device we had created.<\/p>\n<h3>Getting parameters from IRP<span style=\"font-weight: normal; font-size: 13px;\">.<\/span><\/h3>\n<p>In the other OnRead() and OnWrite() Dispatch Functions, we must get data that the driver needs to execute the IRP, such as buffer posted by the user and its size, both in writing and reading.\u00a0These parameters are into a <strong>Stack Location<\/strong> within the IRP.\u00a0<strong>Wow, the more I pray, the more weird names appear to me<\/strong>&#8230;\u00a0Stack Locations structures are parameters that are allocated along with the IRP.\u00a0There is a Stack Location for each device in the device stack that was called.\u00a0This conversation can become quite fun, but we have a post to finish.\u00a0Let&#8217;s leave this subject about Stack Locations to our future filter example.\u00a0There, the matter makes more sense,\u00a0but if you cannot take such a curiosity and want to know more about it, see what the reference says about <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms795764.aspx\">Stack Locations<\/a>.\u00a0For now, let&#8217;s just consider that these parameters are there and to have access to this structure we need to use <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms801624.aspx\">IoGetCurrentIrpStackLocation()<\/a> macro.\u00a0To have a more practical idea of all this bullshit, here it goes all the <em>OnWrite()<\/em> function code with tons of comments.<\/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: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     OnWrite<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      This routine is called, whenever an application calls WriteFile()<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      using our device handle as a parameter.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">*\/<\/span><\/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<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">OnWrite(IN PDEVICE_OBJECT  pDeviceObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        IN PIRP            pIrp)<\/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;\">    PIO_STACK_LOCATION  pStack;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PVOID               pUserBuffer;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ULONG               ulSize;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PBUFFER_ENTRY       pBufferEntry = NULL;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    NTSTATUS            nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    BOOLEAN             bMutexAcquired = FALSE;<\/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;\">__try<\/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: green;\">\/\/-f--&gt; Say hello to the debugger<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KdPrint((<span style=\"color: #a31515;\">\"Writing into EchoDevice...\\n\"<\/span>));<\/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; The Buffer address is a parameter that comes<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      from the IRP<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pUserBuffer = (PCHAR)pIrp-&gt;AssociatedIrp.SystemBuffer;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ASSERT(pUserBuffer != NULL);<\/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: green;\">\/\/-f--&gt; Get the current stack location address from the IRP<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pStack = IoGetCurrentIrpStackLocation(pIrp);<\/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; Get the buffer size<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ulSize = pStack-&gt;Parameters.Write.Length;<\/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: green;\">\/\/-f--&gt; Here, the node and the string buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      are allocated all together<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pBufferEntry = (PBUFFER_ENTRY) ExAllocatePoolWithTag(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            PagedPool,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: blue;\">sizeof<\/span>(BUFFER_ENTRY) + ulSize,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ECHO_TAG);<\/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; If there is no memory, forget it...<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!pBufferEntry)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExRaiseStatus(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; Initializing the structure<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pBufferEntry-&gt;pBuffer = (pBufferEntry + <span style=\"color: purple;\">1<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pBufferEntry-&gt;ulSize = ulSize;<\/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; Do the copy string from the buffer sent by the user<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      to the buffer allocated here.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        RtlCopyMemory(pBufferEntry-&gt;pBuffer,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      pUserBuffer,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      ulSize);<\/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; Acquire the mutex that protect the list<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      against simultaneous accesses.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = KeWaitForMutexObject(&amp;g_Mutex,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                   UserRequest,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                   KernelMode,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                   FALSE,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                   NULL);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExRaiseStatus(nts);<\/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; We need to remember this in case something<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      really bad happens.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        bMutexAcquired = TRUE;<\/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; Insert the new node to the list's tail.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        InsertTailList(&amp;g_BufferList,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                       &amp;pBufferEntry-&gt;Entry);<\/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; Tell the IoManager that all data sent<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      to the driver were read successfully.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pIrp-&gt;IoStatus.Information = ulSize;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = STATUS_SUCCESS;<\/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;\">__except<\/span>(EXCEPTION_EXECUTE_HANDLER)<\/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: green;\">\/\/-f--&gt; Get the error code.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = GetExceptionCode();<\/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; That will force the debugger to stop here.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      But only when compiled in Checked mode.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        ASSERT(FALSE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        KdPrint((<span style=\"color: #a31515;\">\"An exception occurred at \"<\/span> __FUNCTION__ <span style=\"color: #a31515;\">\"\\n\"<\/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: green;\">\/\/-f--&gt; If something gets wrong and we have already allocated<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      this buffer, so let's release it.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (pBufferEntry)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExFreePool(pBufferEntry);<\/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; Tell the IoManager the no data were transferred.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pIrp-&gt;IoStatus.Information = <span style=\"color: purple;\">0<\/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;\"> <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Release the mutex<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">if<\/span> (bMutexAcquired)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeReleaseMutex(&amp;g_Mutex,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                       FALSE);<\/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: green;\">\/\/-f--&gt; Complete the IRP.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pIrp-&gt;IoStatus.Status = nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IoCompleteRequest(pIrp, IO_NO_INCREMENT);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<p>Another important point to notice here is about filling the <em>Information<\/em> member on <em>IoStatus<\/em> structure that is in the IRP. In those data transfer functions, this field informs IoManager the data amount that was transferred from the application to the driver and vice versa.\u00a0This field directly\u00a0reflects on the fourth parameter of WriteFile() API, which has exactly the same function.\u00a0Once received and validated the parameters, we allocate a node that will receive the buffer.\u00a0Notice that we are allocating in <em>paged memory<\/em>; after all, all our functions will be executed in <strong>PASSIVE_LEVEL<\/strong>.\u00a0Although this function is a Dispatch Function, it\u00a0does not mean that it runs in <strong>DISPATCH_LEVEL<\/strong>.\u00a0Take it easy, these are very different things.\u00a0Noting&#8230;\u00a0<em>&#8220;Post about IRQLs and POOL_TYPEs&#8221;<\/em>.\u00a0The <em>OnRead() <\/em>function is similar to OnWrite(), so I&#8217;ll spare you of putting all code here.<\/p>\n<h3>When my driver is unloaded<\/h3>\n<p><em>OnDriverUnload()<\/em> function will be called when the driver is being unloaded.\u00a0Here, in addition to empty the buffer\u00a0list that may have been forgotten in the driver, let&#8217;s delete the Symbolic Link and DeviceObject that was created at startup time.\u00a0Simple as that&#8230;<\/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: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     OnDriverUnload<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      The party is over, go home, regards for your wife<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      and a kiss in your kids.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">*\/<\/span><\/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;\">VOID OnDriverUnload(IN PDRIVER_OBJECT   pDriverObj)<\/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;\">    PLIST_ENTRY     pEntry;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PBUFFER_ENTRY   pBufferEntry;<\/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: green;\">\/\/-f--&gt; Say good night<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    KdPrint((<span style=\"color: #a31515;\">\"Terminating KernelEcho driver...\\n\"<\/span>));<\/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; Here we remove all nodes that weren't read by<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      the application. That would happen if the application call<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      WriteFile() but not ReadFile().<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">while<\/span>(!IsListEmpty(&amp;g_BufferList))<\/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: green;\">\/\/-f--&gt; Take the first list node.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pEntry = RemoveHeadList(&amp;g_BufferList);<\/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; Get the outer structure from its node address.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pBufferEntry = CONTAINING_RECORD(pEntry, BUFFER_ENTRY, Entry);<\/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: green;\">\/\/-f--&gt; Finally, release the memory used by<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      this node.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ExFreePool(pBufferEntry);<\/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;\">    <span style=\"color: green;\">\/\/-f--&gt; Deleting DeviceObject and SymbolicLink<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      created at startup time.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IoDeleteSymbolicLink(&amp;g_usSymbolicLink);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IoDeleteDevice(pDriverObj-&gt;DeviceObject);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<p><strong>Wow, that horrible mistake! What if the driver is finished while some reading or writing operation is being performed?\u00a0Does a dark future await us and our souls will be damned for eternity?\u00a0Does the <a href=\"http:\/\/www.youtube.com\/watch?v=197wJSbSBbs\">Little Mermaid<\/a><\/strong><strong> have something to do with it?<\/strong><\/p>\n<p>Well, better to let our beliefs aside and focus on the DDK.\u00a0A driver cannot be terminated while there are some references to this device driver.\u00a0Note that this routine has no return so, we cannot tell the system that the driver may or may not be unloaded.\u00a0If an application still has an opened\u00a0handle to any device while you ask to stop it, the system will respond that the driver cannot be terminated.\u00a0In this condition, the <em>OnDriverUnload()<\/em> routine will not be called.\u00a0But otherwise, if nothing prevents the driver from being unloaded and our routine is called, forget it&#8230;\u00a0Your driver is already going to driver&#8217;s heaven.<\/p>\n<h3>The wonderful world of Userland<\/h3>\n<p>I will not put all the application\u00a0source code in the post, but all sources are on a file available for downloading.\u00a0I think one thing that&#8217;s worth showing here is the syntax of how to get the handle to the device we have created in our sample driver.<\/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: green;\">\/\/-f--&gt; Here we open a handle to the device that<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      was created by the driver. Remember that our<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      sample driver must be installed and be working,<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      in order the call bellow can work correctly.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    hDevice = CreateFile(<span style=\"color: #a31515;\">\"\\\\\\\\.\\\\EchoDevice\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         GENERIC_ALL,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         <span style=\"color: purple;\">0<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         NULL,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         OPEN_EXISTING,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         <span style=\"color: purple;\">0<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         NULL);<\/pre>\n<\/div>\n<p>Once the handle to the device is obtained, the Read, Write and Close operations will follow exactly as if we were performing the same operations with files. You don&#8217;t need to be a Jedi\u00a0master to be able to use these functions.<\/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: green;\">\/\/-f--&gt; It sends the received string to the driver via<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      WriteFile.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">if<\/span> (!WriteFile(hDevice,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                   szBuffer,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                   dwBytes,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                   &amp;dwBytes,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                   NULL))<\/pre>\n<\/div>\n<h3>Installing and testing<\/h3>\n<p>I have shown in <a href=\"https:\/\/driverentry.com.br\/en\/2006\/09\/11\/getting-started\/\">another post<\/a> how to install a driver by hand. However, there are more civilized ways to install a driver. One of them is using the <a href=\"http:\/\/www.osronline.com\/article.cfm?article=157\">OSR Driver Loader<\/a>, a tool that is offered by OSR to install your driver without rebooting the machine. Actually, this is a very simple procedure to do, but not simple enough to comment about it yet in this post, so let&#8217;s use the tool for now.<\/p>\n<p>After compiling the driver, put a copy of it in the <em>System32\\drivers<\/em> of the victim machine.\u00a0Then run the DriverLoader and fill in the fields as shown in the figure below.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/DriverLoader.png\" alt=\"\" \/><\/div>\n<p>Then click on <em>Register Service<\/em> to install the new driver and then click on <em>Start Service<\/em> to start the driver.\u00a0Okay, now you can use the test application.\u00a0The application is very simple to use.\u00a0Once started, enter the strings that should be sent to the driver.\u00a0An empty string indicates the end of the strings and then it starts reading the same string queued in the driver.<\/p>\n<p>Phew! As we have seen, even a driver that does something simple requires a considerable amount of code and many different concepts. I know that some gaps are remained in the post, but I hope I have helped. If you have questions at some points at driver or even at test application, do not hesitate to ask or send your comments. The contacts are very helpful to define the next posts.<br \/>\n Have fun!<\/p>\n<p><br class=\"spacer_\" \/><\/p>\n<p class=\"download\"><a href=\"http:\/\/www.driverentry.com.br\/samples\/KernelEcho.zip\">KernelEcho.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few months after my hiring into Open, they asked me to do a participation in a lecture about Secure Code. My part was about stack overflow and how to take advantage of that oversight programmer to break into the program. The major point to note was in addition to programmers, the audience was composed [&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-147","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/147","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=147"}],"version-history":[{"count":1,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/147\/revisions"}],"predecessor-version":[{"id":148,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/147\/revisions\/148"}],"wp:attachment":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/media?parent=147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/categories?post=147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/tags?post=147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}