{"componentChunkName":"component---src-templates-post-template-js","path":"/windows-windriver-002-irp-en","result":{"data":{"markdownRemark":{"id":"f1feb68f-e978-537f-b230-146fd4cb3fbc","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/windows-windriver-002-irp\">original page</a>.</p>\n</blockquote>\n<p>I hit a wall when trying Windows kernel debugging: there are very few kernel drivers whose detailed specifications are publicly available.</p>\n<p>So I decided that if none existed, I would just build one myself, and started developing a kernel driver.</p>\n<p>When working on kernel driver development, I am basically proceeding with the following book as a reference.</p>\n<p>Reference: <a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a></p>\n<p>I summarized how to configure kernel debugging in the following article.</p>\n<p>Reference: <a href=\"/windows-windbg-004-kernel-debug\">First steps for kernel debugging a Windows 10 environment with WinDbg</a></p>\n<p>In the <a href=\"/windows-windriver-001-tutorial-en\">previous article</a>, I set up DebugView, created a driver that only outputs the OS version with KdPrint, and performed live debugging.</p>\n<p>This time I want to create a driver with a bit more behavior and debug it.</p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li>\n<p><a href=\"#kernel-programming\">Kernel programming</a></p>\n<ul>\n<li><a href=\"#how-kernel-driver-development-differs-from-user-mode\">How kernel driver development differs from user mode</a></li>\n<li><a href=\"#structured-exception-handling-seh\">Structured Exception Handling (SEH)</a></li>\n<li><a href=\"#kernel-functions\">Kernel functions</a></li>\n<li><a href=\"#memory-allocation-in-kernel-drivers\">Memory allocation in kernel drivers</a></li>\n<li><a href=\"#device-objects\">Device objects</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#creating-a-kernel-driver-and-client-application\">Creating a kernel driver and client application</a></p>\n<ul>\n<li><a href=\"#scheduling-priorities\">Scheduling priorities</a></li>\n<li><a href=\"#creating-the-driverentry-function\">Creating the DriverEntry function</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#reading-the-driverentry-function\">Reading the DriverEntry function</a></p>\n<ul>\n<li><a href=\"#supporting-dispatch-routines\">Supporting dispatch routines</a></li>\n<li><a href=\"#strings-used-by-kernel-functions\">Strings used by kernel functions</a></li>\n<li><a href=\"#creating-a-device-object\">Creating a device object</a></li>\n<li><a href=\"#creating-a-symbolic-link\">Creating a symbolic link</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#setting-up-the-routines-assigned-to-the-dispatch-routines\">Setting up the routines assigned to the dispatch routines</a></p>\n<ul>\n<li><a href=\"#function-annotations\">Function annotations</a></li>\n<li><a href=\"#receiving-irps\">Receiving IRPs</a></li>\n<li><a href=\"#setting-up-device-control\">Setting up device control</a></li>\n<li><a href=\"#obtaining-the-current-stack-location\">Obtaining the current stack location</a></li>\n<li><a href=\"#setting-the-requested-priority-on-the-thread\">Setting the requested priority on the thread</a></li>\n</ul>\n</li>\n<li><a href=\"#installing-the-driver\">Installing the driver</a></li>\n<li>\n<p><a href=\"#checking-the-behavior-with-kernel-debugging\">Checking the behavior with kernel debugging</a></p>\n<ul>\n<li><a href=\"#setting-a-breakpoint\">Setting a breakpoint</a></li>\n<li><a href=\"#analyzing-irps\">Analyzing IRPs</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n<li><a href=\"#reference-books\">Reference books</a></li>\n</ul>\n<h2 id=\"kernel-programming\" style=\"position:relative;\"><a href=\"#kernel-programming\" aria-label=\"kernel programming permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Kernel programming</h2>\n<p>I am developing this kernel driver based on <a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a>.</p>\n<p>The WDK (Windows Driver Kit) that I installed last time contains the libraries and header files used for kernel driver development.</p>\n<p>Kernel APIs are composed of C-language functions, but they differ from user-mode development mainly in the following ways.</p>\n<h3 id=\"how-kernel-driver-development-differs-from-user-mode\" style=\"position:relative;\"><a href=\"#how-kernel-driver-development-differs-from-user-mode\" aria-label=\"how kernel driver development differs from user mode permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How kernel driver development differs from user mode</h3>\n<p>Below is a quotation from <a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a> about how kernel driver development differs from user mode development.</p>\n<ul>\n<li>Unhandled exceptions crash the system (BSOD)</li>\n<li>Resources must be released in the unload routine when the driver is unloaded (otherwise leaks occur)</li>\n<li>Errors during kernel driver development must never be ignored</li>\n<li>IRQL can be greater than 0</li>\n<li>Embedded bugs can affect the entire system</li>\n<li>Debugging must be done remotely from another machine</li>\n<li>Most standard libraries are unavailable</li>\n<li>Only <code class=\"language-text\">Structured Exception Handling (SEH)</code> can be used for exception handling</li>\n<li>The C++ runtime is unavailable</li>\n</ul>\n<h3 id=\"structured-exception-handling-seh\" style=\"position:relative;\"><a href=\"#structured-exception-handling-seh\" aria-label=\"structured exception handling seh permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Structured Exception Handling (SEH)</h3>\n<p>SEH is a feature for appropriately handling situations with specific exception codes, such as hardware failures.</p>\n<p>By using SEH, you can write programs that properly release resources such as memory blocks and files even when an exception occurs.</p>\n<p>SEH provides two mechanisms: an “exception handler” and a “termination handler”.</p>\n<p>Exception handlers are used to deal with specific errors.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/cpp/cpp/writing-an-exception-handler?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Writing an Exception Handler | Microsoft Docs</a></p>\n<p>Meanwhile, a termination handler can be made to run regardless of whether a code block finishes normally or an exception occurs.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/cpp/cpp/writing-a-termination-handler?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Writing a Termination Handler | Microsoft Docs</a></p>\n<p>When developing kernel drivers, you need to use SEH and implement exception handling with one of the mechanisms above.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Structured Exception Handling (C/C++) | Microsoft Docs</a></p>\n<h3 id=\"kernel-functions\" style=\"position:relative;\"><a href=\"#kernel-functions\" aria-label=\"kernel functions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Kernel functions</h3>\n<p>In kernel driver development, the C standard library is basically unavailable.</p>\n<p>Instead, kernel driver development uses functions exported from kernel components.</p>\n<p>Many kernel functions are implemented in <code class=\"language-text\">Ntoskrnl.exe</code>.</p>\n<p>Some of the functions implemented in <code class=\"language-text\">Ntoskrnl.exe</code> are documented, while others are not.</p>\n<p>Kernel function names follow certain conventions, and prefixes are attached according to purpose.</p>\n<p>The following Wikipedia page had a detailed explanation of the prefix mappings.</p>\n<p>Reference: <a href=\"https://en.wikipedia.org/wiki/Ntoskrnl.exe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ntoskrnl.exe - Wikipedia</a></p>\n<p>Documented kernel functions can be referenced on pages such as the following.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/windows-hardware/drivers/ddi/_kernel/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows kernel - Windows drivers | Microsoft Docs</a></p>\n<h3 id=\"memory-allocation-in-kernel-drivers\" style=\"position:relative;\"><a href=\"#memory-allocation-in-kernel-drivers\" aria-label=\"memory allocation in kernel drivers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Memory allocation in kernel drivers</h3>\n<p>The kernel provides the following two memory pools that drivers can use.</p>\n<ul>\n<li>Paged pool: an area that can be paged out as needed</li>\n<li>Nonpaged pool: an area that is never paged out</li>\n</ul>\n<p>In addition, the nonpaged pool can separately control executable and non-executable regions.</p>\n<p>Using nonpaged pool that is not paged out guarantees that page faults will not occur, but it seems that when developing drivers, using paged pool as much as possible is recommended.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exallocatepool\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ExAllocatePool function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<h3 id=\"device-objects\" style=\"position:relative;\"><a href=\"#device-objects\" aria-label=\"device objects permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Device objects</h3>\n<p>As a rule, a kernel driver needs to create one or more device objects.</p>\n<p>A device object is what the OS uses to represent a device.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/windows-hardware/drivers/kernel/introduction-to-device-objects\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Introduction to Device Objects - Windows drivers | Microsoft Docs</a></p>\n<p>A device object is created as an instance of the <code class=\"language-text\">DEVICE_OBJECT</code> structure.</p>\n<p>Kernel drivers communicate with client applications through device objects.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_device_object\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><em>DEVICE</em>OBJECT (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<h2 id=\"creating-a-kernel-driver-and-client-application\" style=\"position:relative;\"><a href=\"#creating-a-kernel-driver-and-client-application\" aria-label=\"creating a kernel driver and client application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a kernel driver and client application</h2>\n<p>I will develop SecondDriverSample while transcribing the code explained in Chapter 4 of <a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a>.</p>\n<p>In Chapter 4, a set consisting of a kernel driver and a client application that controls thread priority is created.</p>\n<h3 id=\"scheduling-priorities\" style=\"position:relative;\"><a href=\"#scheduling-priorities\" aria-label=\"scheduling priorities permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Scheduling priorities</h3>\n<p>To be honest, I did not really know what setting thread priority with the Windows API meant, so I looked into it briefly.</p>\n<p>In Windows, threads are scheduled according to thread priority.</p>\n<p>Thread priority is determined by the following two conditions.</p>\n<ul>\n<li>Process priority class</li>\n<li>Thread priority level within the process priority class</li>\n</ul>\n<p>The process priority class can be set to one of the following and can be configured with <code class=\"language-text\">SetPriorityClass</code>.</p>\n<p>By default, the process priority class seems to be <code class=\"language-text\">THREAD_PRIORITY_NORMAL</code>.</p>\n<ul>\n<li>THREAD<em>PRIORITY</em>IDLE</li>\n<li>THREAD<em>PRIORITY</em>LOWEST</li>\n<li>THREAD<em>PRIORITY</em>BELOW_NORMAL</li>\n<li>THREAD<em>PRIORITY</em>NORMAL</li>\n<li>THREAD<em>PRIORITY</em>ABOVE_NORMAL</li>\n<li>THREAD<em>PRIORITY</em>HIGHEST</li>\n<li>THREAD<em>PRIORITY</em>TIME_CRITICAL</li>\n</ul>\n<p>On the other hand, one of the following thread priority levels is set within each priority class.</p>\n<p>It can be changed with <code class=\"language-text\">SetThreadPriority</code>.</p>\n<p>Here as well, <code class=\"language-text\">THREAD_PRIORITY_NORMAL</code> is assigned by default.</p>\n<ul>\n<li>THREAD<em>PRIORITY</em>IDLE</li>\n<li>THREAD<em>PRIORITY</em>LOWEST</li>\n<li>THREAD<em>PRIORITY</em>BELOW_NORMAL</li>\n<li>THREAD<em>PRIORITY</em>NORMAL</li>\n<li>THREAD<em>PRIORITY</em>ABOVE_NORMAL</li>\n<li>THREAD<em>PRIORITY</em>HIGHEST</li>\n<li>THREAD<em>PRIORITY</em>TIME_CRITICAL</li>\n</ul>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">SetPriorityClass function (processthreadsapi.h) - Win32 apps | Microsoft Docs</a></p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">SetThreadPriority function (processthreadsapi.h) - Win32 apps | Microsoft Docs</a></p>\n<p>Although each thread’s priority is determined by a combination of these settings, as shown in the table at the link below, it seems that not all priority levels can be flexibly set with the usual configuration methods.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/windows/win32/procthread/scheduling-priorities\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Scheduling Priorities - Win32 apps | Microsoft Docs</a></p>\n<p>Therefore, the goal of the driver and client developed in Chapter 4 is to make thread priority configurable more flexibly.</p>\n<h3 id=\"creating-the-driverentry-function\" style=\"position:relative;\"><a href=\"#creating-the-driverentry-function\" aria-label=\"creating the driverentry function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating the DriverEntry function</h3>\n<p>The base procedure is the same as the one I used in the <a href=\"/windows-windriver-001-tutorial-en\">earlier article</a>.</p>\n<p>First, create the <code class=\"language-text\">DriverEntry</code> function, which will serve as the entry point.</p>\n<p>In the <code class=\"language-text\">DriverEntry</code> function, implement the following processing.</p>\n<ul>\n<li>Set the unload routine</li>\n<li>Set the dispatch routines supported by the driver</li>\n<li>Create the device object</li>\n<li>Create a symbolic link to the device object</li>\n</ul>\n<p>As mentioned earlier, that is why the unload routine and device object are necessary.</p>\n<p>For details, the “Required Standard Driver Routines” section below is helpful.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/windows-hardware/drivers/kernel/introduction-to-standard-driver-routines\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Introduction to Standard Driver Routines - Windows drivers | Microsoft Docs</a></p>\n<p>Dispatch routines are what process IRPs (incoming I/O request packets).</p>\n<p>IRPs store information about many different kinds of requests.</p>\n<p>To open the driver’s device handle, a kernel driver apparently needs to support at least the dispatch routines for <code class=\"language-text\">IRP_MJ_CREATE</code> and <code class=\"language-text\">IRP_MJ_CLOSE</code>.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/windows-hardware/drivers/kernel/dispatch-routine-functionality\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Dispatch Routine Functionality - Windows drivers | Microsoft Docs</a></p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nc-wdm-driver_dispatch\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DRIVER_DISPATCH (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/dispatchcreate--dispatchclose--and-dispatchcreateclose-routines\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DispatchCreate, DispatchClose, and DispatchCreateClose Routines - Windows drivers | Microsoft Docs</a></p>\n<p>A symbolic link to the device object is created so that the client can reference the kernel driver’s device object.</p>\n<p>For example, functions such as <code class=\"language-text\">CreateFile</code> take the symbolic link to the device object as their first argument.</p>\n<h2 id=\"reading-the-driverentry-function\" style=\"position:relative;\"><a href=\"#reading-the-driverentry-function\" aria-label=\"reading the driverentry function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reading the DriverEntry function</h2>\n<p>Now, the <code class=\"language-text\">DriverEntry</code> function that I actually created while transcribing the code looked like this.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">extern</span> <span class=\"token string\">\"C\"</span> NTSTATUS\n<span class=\"token function\">DriverEntry</span><span class=\"token punctuation\">(</span>_In_ PDRIVER_OBJECT DriverObject<span class=\"token punctuation\">,</span> _In_ PUNICODE_STRING RegistryPath<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token function\">UNREFERENCED_PARAMETER</span><span class=\"token punctuation\">(</span>RegistryPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SecondDriver DriverEntry started\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\tDriverObject<span class=\"token operator\">-></span>DriverUnload <span class=\"token operator\">=</span> SecondDriverUnload<span class=\"token punctuation\">;</span>\n\n\tDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CREATE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span>\n\tDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CLOSE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span>\n\tDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_DEVICE_CONTROL<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverDeviceControl<span class=\"token punctuation\">;</span>\n\n\tUNICODE_STRING devName <span class=\"token operator\">=</span> <span class=\"token function\">RTL_CONSTANT_STRING</span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"\\\\Device\\\\SecondDriver\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t<span class=\"token comment\">//RtlInitUnicodeString(&amp;devName, L\"\\\\Device\\\\ThreadBoost\");</span>\n\tPDEVICE_OBJECT DeviceObject<span class=\"token punctuation\">;</span>\n\tNTSTATUS status <span class=\"token operator\">=</span> <span class=\"token function\">IoCreateDevice</span><span class=\"token punctuation\">(</span>DriverObject<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>devName<span class=\"token punctuation\">,</span> FILE_DEVICE_UNKNOWN<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> FALSE<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>DeviceObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Failed to create device (0x%08X)\\n\"</span><span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">return</span> status<span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\tUNICODE_STRING symLink <span class=\"token operator\">=</span> <span class=\"token function\">RTL_CONSTANT_STRING</span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"\\\\??\\\\SecondDriver\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\tstatus <span class=\"token operator\">=</span> <span class=\"token function\">IoCreateSymbolicLink</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>symLink<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>devName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Failed to create symbolic link (0x%08X)\\n\"</span><span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token function\">IoDeleteDevice</span><span class=\"token punctuation\">(</span>DeviceObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">return</span> status<span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SecondDriverSecondDriver DriverEntry completed successfully\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t<span class=\"token keyword\">return</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"supporting-dispatch-routines\" style=\"position:relative;\"><a href=\"#supporting-dispatch-routines\" aria-label=\"supporting dispatch routines permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Supporting dispatch routines</h3>\n<p>For the time being, the following three lines were what caught my attention.</p>\n<p>This is where the dispatch routines are set up.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">DriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CREATE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span>\nDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CLOSE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span>\nDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_DEVICE_CONTROL<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverDeviceControl<span class=\"token punctuation\">;</span></code></pre></div>\n<p><code class=\"language-text\">DriverObject</code> is a <code class=\"language-text\">semi-documented</code> structure that represents the image of a loaded kernel-mode driver.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">_DRIVER_OBJECT</span> <span class=\"token punctuation\">{</span>\n  CSHORT             Type<span class=\"token punctuation\">;</span>\n  CSHORT             Size<span class=\"token punctuation\">;</span>\n  PDEVICE_OBJECT     DeviceObject<span class=\"token punctuation\">;</span>\n  ULONG              Flags<span class=\"token punctuation\">;</span>\n  PVOID              DriverStart<span class=\"token punctuation\">;</span>\n  ULONG              DriverSize<span class=\"token punctuation\">;</span>\n  PVOID              DriverSection<span class=\"token punctuation\">;</span>\n  PDRIVER_EXTENSION  DriverExtension<span class=\"token punctuation\">;</span>\n  UNICODE_STRING     DriverName<span class=\"token punctuation\">;</span>\n  PUNICODE_STRING    HardwareDatabase<span class=\"token punctuation\">;</span>\n  PFAST_IO_DISPATCH  FastIoDispatch<span class=\"token punctuation\">;</span>\n  PDRIVER_INITIALIZE DriverInit<span class=\"token punctuation\">;</span>\n  PDRIVER_STARTIO    DriverStartIo<span class=\"token punctuation\">;</span>\n  PDRIVER_UNLOAD     DriverUnload<span class=\"token punctuation\">;</span>\n  PDRIVER_DISPATCH   MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_MAXIMUM_FUNCTION <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> DRIVER_OBJECT<span class=\"token punctuation\">,</span> <span class=\"token operator\">*</span>PDRIVER_OBJECT<span class=\"token punctuation\">;</span></code></pre></div>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_driver_object\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><em>DRIVER</em>OBJECT (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>What does “the image of a loaded kernel-mode driver” actually mean? My understanding is that it is an object allocated and initialized by the kernel before <code class=\"language-text\">DriverEntry</code> is called, so I figure it is an object the kernel kindly sets up for us. (I still could not quite figure it out even after looking it up…)</p>\n<p>Here, by registering dispatch routines in <code class=\"language-text\">MajorFunction</code>, which is a member of this driver object, you can specify the concrete functions supported by the driver.</p>\n<p><code class=\"language-text\">MajorFunction</code> is managed as an array of function pointers, and indices prefixed with <code class=\"language-text\">IRP_MJ_</code> are predefined.</p>\n<p>The reason you only need to add the dispatch routines you support is that when the <code class=\"language-text\">MajorFunction</code> array is initialized by the kernel, all elements are set to <code class=\"language-text\">nt!IopInvalidDeviceRequest</code>, which indicates IRPs not supported by the driver.</p>\n<p>For that reason, only the dispatch routines you support are updated.</p>\n<p>Reference: <a href=\"https://social.msdn.microsoft.com/Forums/ja-JP/4f42ce1d-cbd1-4968-b458-1d96239368a8/driverobject-12392-driverentry?forum=wdksupportteamja\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DriverObject and DriverEntry</a></p>\n<h3 id=\"strings-used-by-kernel-functions\" style=\"position:relative;\"><a href=\"#strings-used-by-kernel-functions\" aria-label=\"strings used by kernel functions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Strings used by kernel functions</h3>\n<p>When using strings with kernel functions, a structure of type <code class=\"language-text\">UNICODE_STRING</code> is basically expected.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><em>UNICODE</em>STRING (ntdef.h) - Win32 apps | Microsoft Docs</a></p>\n<p>In the following lines of source code, the <code class=\"language-text\">RTL_CONSTANT_STRING</code> macro converts the path string <code class=\"language-text\">\\\\Device\\\\SecondDriver</code> into a <code class=\"language-text\">UNICODE_STRING</code> and stores it in the variable <code class=\"language-text\">devName</code>.</p>\n<p>The later <code class=\"language-text\">symLink</code> line works the same way.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">UNICODE_STRING devName <span class=\"token operator\">=</span> <span class=\"token function\">RTL_CONSTANT_STRING</span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"\\\\Device\\\\SecondDriver\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nUNICODE_STRING symLink <span class=\"token operator\">=</span> <span class=\"token function\">RTL_CONSTANT_STRING</span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"\\\\??\\\\SecondDriver\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlinitstring\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">RtlInitString function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<h3 id=\"creating-a-device-object\" style=\"position:relative;\"><a href=\"#creating-a-device-object\" aria-label=\"creating a device object permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a device object</h3>\n<p>The required “creation of a device object” inside the <code class=\"language-text\">DriverEntry</code> function happens here.</p>\n<p>Although we already receive the kernel-initialized <code class=\"language-text\">DriverObject</code> as an argument to <code class=\"language-text\">DriverEntry</code>, it provides the information needed to create a device object with the <code class=\"language-text\">IoCreateDevice</code> function.</p>\n<p>If no device object exists, there is no way for a user-mode client to open a handle and communicate with the driver.</p>\n<p>A device object is created with the <code class=\"language-text\">IoCreateDevice</code> function.</p>\n<p>The <code class=\"language-text\">IoCreateDevice</code> function has the following form.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">NTSTATUS <span class=\"token function\">IoCreateDevice</span><span class=\"token punctuation\">(</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           PDRIVER_OBJECT  DriverObject<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           ULONG           DeviceExtensionSize<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">,</span> optional<span class=\"token punctuation\">]</span> PUNICODE_STRING DeviceName<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           DEVICE_TYPE     DeviceType<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           ULONG           DeviceCharacteristics<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           BOOLEAN         Exclusive<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>out<span class=\"token punctuation\">]</span>          PDEVICE_OBJECT  <span class=\"token operator\">*</span>DeviceObject\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iocreatedevice\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IoCreateDevice function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>The <code class=\"language-text\">DriverObject</code> of type <code class=\"language-text\">PDRIVER_OBJECT</code> received as the first argument is the one that was passed in as an argument to <code class=\"language-text\">DriverEntry</code>.</p>\n<p>The seventh argument receives a pointer to the newly created <code class=\"language-text\">DeviceObject</code> structure.</p>\n<p>Here, we pass a pointer to the newly declared <code class=\"language-text\">DeviceObject</code> of type <code class=\"language-text\">PDEVICE_OBJECT</code>.</p>\n<p>If the <code class=\"language-text\">IoCreateDevice</code> function runs successfully, the location referenced by this pointer is filled with a device object allocated from nonpaged pool.</p>\n<p>In addition, the third argument <code class=\"language-text\">DeviceName</code> lets you name the device object being created.</p>\n<p>Here, we set the <code class=\"language-text\">devName</code> defined earlier.</p>\n<p>For <code class=\"language-text\">DeviceType</code>, specify <code class=\"language-text\">FILE_DEVICE_UNKNOWN</code>.</p>\n<p>The documentation below summarizes other device types that can be set.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/specifying-device-types\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Specifying Device Types - Windows drivers | Microsoft Docs</a></p>\n<p>The actual code looks like this.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">PDEVICE_OBJECT DeviceObject<span class=\"token punctuation\">;</span>\nNTSTATUS status <span class=\"token operator\">=</span> <span class=\"token function\">IoCreateDevice</span><span class=\"token punctuation\">(</span>DriverObject<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>devName<span class=\"token punctuation\">,</span> FILE_DEVICE_UNKNOWN<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> FALSE<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>DeviceObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Failed to create device (0x%08X)\\n\"</span><span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">return</span> status<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If the operation fails, an error message is output with the <code class=\"language-text\">KdPrint</code> function.</p>\n<h3 id=\"creating-a-symbolic-link\" style=\"position:relative;\"><a href=\"#creating-a-symbolic-link\" aria-label=\"creating a symbolic link permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a symbolic link</h3>\n<p>The device object has now been created, but user-mode clients still cannot access it as-is.</p>\n<p>To allow a user-mode client to access the device driver, you need to create a symbolic link to the device object.</p>\n<p>A symbolic link is created with the <code class=\"language-text\">IoCreateSymbolicLink</code> function.</p>\n<p>The function itself is simple: you just pass the symbolic link and the device object name, converted into <code class=\"language-text\">PUNICODE_STRING</code> structures, as arguments.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iocreatesymboliclink\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IoCreateSymbolicLink function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>The actual code looks like this.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">UNICODE_STRING symLink <span class=\"token operator\">=</span> <span class=\"token function\">RTL_CONSTANT_STRING</span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"\\\\??\\\\SecondDriver\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nstatus <span class=\"token operator\">=</span> <span class=\"token function\">IoCreateSymbolicLink</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>symLink<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>devName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Failed to create symbolic link (0x%08X)\\n\"</span><span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token function\">IoDeleteDevice</span><span class=\"token punctuation\">(</span>DeviceObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">return</span> status<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If creating the symbolic link fails, all of the work done so far needs to be rolled back and the function should exit.</p>\n<p>Here, the <code class=\"language-text\">IoDeleteDevice</code> function is used to delete the device object from the system.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iodeletedevice\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IoDeleteDevice function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>Once the device object and symbolic link have been created, the <code class=\"language-text\">DriverEntry</code> processing is complete.</p>\n<h2 id=\"setting-up-the-routines-assigned-to-the-dispatch-routines\" style=\"position:relative;\"><a href=\"#setting-up-the-routines-assigned-to-the-dispatch-routines\" aria-label=\"setting up the routines assigned to the dispatch routines permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up the routines assigned to the dispatch routines</h2>\n<p>Next, let’s set up the routines that support CREATE and CLOSE, which were assigned in the following lines earlier.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">DriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CREATE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span>\nDriverObject<span class=\"token operator\">-></span>MajorFunction<span class=\"token punctuation\">[</span>IRP_MJ_CLOSE<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> SecondDriverCreateClose<span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the program created in Chapter 4, both the CREATE and CLOSE routines are set to the same <code class=\"language-text\">SecondDriverCreateClose</code>.</p>\n<p>That is because its behavior is simply to accept IRP requests without doing any special processing.</p>\n<p>If you want to separate the processing for CREATE and CLOSE, you need to create and assign different routines.</p>\n<p>Let’s look at the actual code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">_Use_decl_annotations_\nNTSTATUS <span class=\"token function\">SecondDriverCreateClose</span><span class=\"token punctuation\">(</span>PDEVICE_OBJECT DeviceObject<span class=\"token punctuation\">,</span> PIRP Irp<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token function\">UNREFERENCED_PARAMETER</span><span class=\"token punctuation\">(</span>DeviceObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\tIrp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Status <span class=\"token operator\">=</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\n\tIrp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Information <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token function\">IoCompleteRequest</span><span class=\"token punctuation\">(</span>Irp<span class=\"token punctuation\">,</span> IO_NO_INCREMENT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">return</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Also, when I actually defined the dispatch routine exactly like the sample in the book, I got compiler error C2440 at build time.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">エラー\tC2440\t<span class=\"token char\">'='</span><span class=\"token operator\">:</span> '<span class=\"token function\">NTSTATUS</span> <span class=\"token punctuation\">(</span>__stdcall <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>PDRIVER_OBJECT<span class=\"token punctuation\">,</span>PIRP<span class=\"token punctuation\">)</span><span class=\"token char\">' から '</span>PDRIVER_DISPATCH' に変換できません。</code></pre></div>\n<p>I honestly did not understand it even after Googling, but when I tried defining the assigned function directly before the <code class=\"language-text\">DriverEntry</code> function instead of just declaring a prototype, it went away.</p>\n<p>I do not know whether that is really the right fix.</p>\n<p>Kernel development with WDM itself is no longer recommended, so maybe the latest compiler is tripping over something.</p>\n<h3 id=\"function-annotations\" style=\"position:relative;\"><a href=\"#function-annotations\" aria-label=\"function annotations permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Function annotations</h3>\n<p>There is <code class=\"language-text\">_Use_decl_annotations_</code> on the first line, but I had no idea what it was for.</p>\n<p>The documentation says that by using <code class=\"language-text\">_Use_decl_annotations_</code>, the annotations shown in the header within the scope of the same function are treated as if they also exist on the definition marked with <code class=\"language-text\">_Use_decl_annotations_</code>.</p>\n<p>Reference: <a href=\"https://stackoverflow.com/questions/24426875/what-is-use-decl-annotations-meaning\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">c++ - what is <em>Use</em>decl<em>annotations</em> meaning - Stack Overflow</a></p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/cpp/code-quality/annotating-function-behavior?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Annotating function behavior | Microsoft Docs</a></p>\n<p>I looked into it for a while, but I still could not understand its purpose, so I may add an update later if I figure it out.</p>\n<h3 id=\"receiving-irps\" style=\"position:relative;\"><a href=\"#receiving-irps\" aria-label=\"receiving irps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Receiving IRPs</h3>\n<p>An IRP is a structure created by the I/O manager when an I/O request occurs from an application.</p>\n<p>IRPs are allocated from nonpaged pool and passed around as data packets.</p>\n<p>Let’s look at the code first.</p>\n<p>What the driver in Chapter 4 does is simple: after it rewrites some values in the <code class=\"language-text\">IoStatus</code> field of the IRP received as an argument, it passes the IRP to <code class=\"language-text\">IoCompleteRequest</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">Irp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Status <span class=\"token operator\">=</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\nIrp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Information <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">IoCompleteRequest</span><span class=\"token punctuation\">(</span>Irp<span class=\"token punctuation\">,</span> IO_NO_INCREMENT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>An IRP roughly consists of an IRP header and a stack location.</p>\n<p>After the I/O manager receives a request from an application, it allocates an IRP in nonpaged pool memory.</p>\n<p>It then initializes the IRP header and stack location and calls the driver’s dispatch routine.</p>\n<p>The following article was extremely helpful for understanding the detailed flow.</p>\n<p>Reference: <a href=\"https://sciencepark.co.jp/device_driver/dvdr/report-25/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Device driver course 25 | Science Park Co., Ltd.</a></p>\n<p><code class=\"language-text\">IoStatus</code> is an I/O status block, and when the IRP completes, its completion state is set in <code class=\"language-text\">IoStatus.Status</code>.</p>\n<p><code class=\"language-text\">IoStatus.Information</code> stores the number of bytes read or written.</p>\n<p>Since nothing is being read or written here, <code class=\"language-text\">IoStatus.Information</code> is set to 0.</p>\n<p>The <code class=\"language-text\">IoCompleteRequest</code> macro is used when a dispatch routine has completely finished processing an I/O request and returns the IRP to the I/O manager.</p>\n<p>This completes the definition of the dispatch routine that supports CREATE and CLOSE.</p>\n<h3 id=\"setting-up-device-control\" style=\"position:relative;\"><a href=\"#setting-up-device-control\" aria-label=\"setting up device control permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up device control</h3>\n<p>Next, set up the device control routine configured by the line <code class=\"language-text\">DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SecondDriverDeviceControl;</code>.</p>\n<p><code class=\"language-text\">DEVICE_CONTROL</code> is a general-purpose routine that can be used when exchanging data with a driver.</p>\n<p><code class=\"language-text\">DEVICE_CONTROL</code> needs to receive three things: an input buffer, an output buffer, and a control code.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-device-control\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IRP<em>MJ</em>DEVICE_CONTROL - Windows drivers | Microsoft Docs</a></p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-i-o-control-codes\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Introduction to I/O Control Codes - Windows drivers | Microsoft Docs</a></p>\n<p>The control codes described in the following documentation are passed to DEVICE_CONTROL, and the operation is determined from them.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DeviceIoControl function (ioapiset.h) - Win32 apps | Microsoft Docs</a></p>\n<p>Let’s look at the actual code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">_Use_decl_annotations_\nNTSTATUS <span class=\"token function\">SecondDriverDeviceControl</span><span class=\"token punctuation\">(</span>PDEVICE_OBJECT<span class=\"token punctuation\">,</span> PIRP Irp<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// get our IO_STACK_LOCATION</span>\n\t<span class=\"token keyword\">auto</span> stack <span class=\"token operator\">=</span> <span class=\"token function\">IoGetCurrentIrpStackLocation</span><span class=\"token punctuation\">(</span>Irp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">auto</span> status <span class=\"token operator\">=</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\n\n\t<span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>IoControlCode<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">case</span> IOCTL_SECOND_DRIVER_SET_PRIORITY<span class=\"token operator\">:</span>\n\t<span class=\"token punctuation\">{</span>\n\t\t<span class=\"token comment\">// do the work</span>\n\t\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>InputBufferLength <span class=\"token operator\">&lt;</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>ThreadData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t\tstatus <span class=\"token operator\">=</span> STATUS_BUFFER_TOO_SMALL<span class=\"token punctuation\">;</span>\n\t\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">}</span>\n\n\t\t<span class=\"token keyword\">auto</span> data <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>ThreadData<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>Type3InputBuffer<span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data <span class=\"token operator\">==</span> nullptr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">}</span>\n\n\t\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">&lt;</span> <span class=\"token number\">1</span> <span class=\"token operator\">||</span> data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">></span> <span class=\"token number\">31</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">}</span>\n\n\t\tPETHREAD Thread<span class=\"token punctuation\">;</span>\n\t\tstatus <span class=\"token operator\">=</span> <span class=\"token function\">PsLookupThreadByThreadId</span><span class=\"token punctuation\">(</span><span class=\"token function\">ULongToHandle</span><span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\t\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n\t\t<span class=\"token function\">KeSetPriorityThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>PKTHREAD<span class=\"token punctuation\">)</span>Thread<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token function\">ObDereferenceObject</span><span class=\"token punctuation\">(</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Thread Priority change for %d to %d succeeded!\\n\"</span><span class=\"token punctuation\">,</span>\n\t\t\tdata<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\t<span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n\t\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_DEVICE_REQUEST<span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\tIrp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Status <span class=\"token operator\">=</span> status<span class=\"token punctuation\">;</span>\n\tIrp<span class=\"token operator\">-></span>IoStatus<span class=\"token punctuation\">.</span>Information <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token function\">IoCompleteRequest</span><span class=\"token punctuation\">(</span>Irp<span class=\"token punctuation\">,</span> IO_NO_INCREMENT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">return</span> status<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"obtaining-the-current-stack-location\" style=\"position:relative;\"><a href=\"#obtaining-the-current-stack-location\" aria-label=\"obtaining the current stack location permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Obtaining the current stack location</h3>\n<p>The <code class=\"language-text\">IoGetCurrentIrpStackLocation</code> function can obtain the current stack location.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">auto</span> stack <span class=\"token operator\">=</span> <span class=\"token function\">IoGetCurrentIrpStackLocation</span><span class=\"token punctuation\">(</span>Irp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>A stack location is defined by the <code class=\"language-text\">IO_STACK_LOCATION</code> structure.</p>\n<p>Drivers use the stack location inside an IRP to obtain driver-specific information related to the I/O operation.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iogetcurrentirpstacklocation\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IoGetCurrentIrpStackLocation function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>A stack location contains information such as the following.</p>\n<ul>\n<li>Information about the <code class=\"language-text\">MajorFunctions</code> executed by the driver</li>\n<li>Information about the <code class=\"language-text\">MinorFunctions</code> executed by the driver</li>\n<li>The length and start position of buffers for data transferred by the driver</li>\n<li>A pointer to the device object created by the driver</li>\n<li>A pointer to a file object that represents an open file, device, directory, or volume</li>\n</ul>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/i-o-stack-locations\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">I/O Stack Locations - Windows drivers | Microsoft Docs</a></p>\n<h3 id=\"setting-the-requested-priority-on-the-thread\" style=\"position:relative;\"><a href=\"#setting-the-requested-priority-on-the-thread\" aria-label=\"setting the requested priority on the thread permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting the requested priority on the thread</h3>\n<p>This is the core implementation of the driver we are building this time.</p>\n<p>It is defined inside the <code class=\"language-text\">SecondDriverDeviceControl</code> function.</p>\n<p>The stack location obtained with the <code class=\"language-text\">IoGetCurrentIrpStackLocation</code> function contains information such as the passed control code.</p>\n<p>Because of that, processing branches based on the information in <code class=\"language-text\">stack->Parameters.DeviceIoControl.IoControlCode</code>.</p>\n<p>The source code is below.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token comment\">// switch (stack->Parameters.DeviceIoControl.IoControlCode)</span>\n<span class=\"token keyword\">case</span> IOCTL_SECOND_DRIVER_SET_PRIORITY<span class=\"token operator\">:</span>\n<span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// do the work</span>\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>InputBufferLength <span class=\"token operator\">&lt;</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>ThreadData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tstatus <span class=\"token operator\">=</span> STATUS_BUFFER_TOO_SMALL<span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\t<span class=\"token keyword\">auto</span> data <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>ThreadData<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>Type3InputBuffer<span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data <span class=\"token operator\">==</span> nullptr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">&lt;</span> <span class=\"token number\">1</span> <span class=\"token operator\">||</span> data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">></span> <span class=\"token number\">31</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span>\n\n\tPETHREAD Thread<span class=\"token punctuation\">;</span>\n\tstatus <span class=\"token operator\">=</span> <span class=\"token function\">PsLookupThreadByThreadId</span><span class=\"token punctuation\">(</span><span class=\"token function\">ULongToHandle</span><span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\t\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n\t<span class=\"token function\">KeSetPriorityThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>PKTHREAD<span class=\"token punctuation\">)</span>Thread<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token function\">ObDereferenceObject</span><span class=\"token punctuation\">(</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Thread Priority change for %d to %d succeeded!\\n\"</span><span class=\"token punctuation\">,</span>\n\t\tdata<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><code class=\"language-text\">IOCTL_SECOND_DRIVER_SET_PRIORITY</code> is defined as follows.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">IOCTL_SECOND_DRIVER_SET_PRIORITY</span> <span class=\"token expression\"><span class=\"token function\">CTL_CODE</span><span class=\"token punctuation\">(</span>SECOND_DRIVER_DEVICE<span class=\"token punctuation\">,</span> <span class=\"token number\">0x800</span><span class=\"token punctuation\">,</span> METHOD_NEITHER<span class=\"token punctuation\">,</span> FILE_ANY_ACCESS<span class=\"token punctuation\">)</span></span></span></code></pre></div>\n<p>The <code class=\"language-text\">CTL_CODE</code> macro generates a control code object from the information in its arguments.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/d4drvif/nf-d4drvif-ctl_code\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CTL_CODE macro (d4drvif.h) - Windows drivers | Microsoft Docs</a></p>\n<p>If the passed control code is <code class=\"language-text\">IOCTL_SECOND_DRIVER_SET_PRIORITY</code>, the processing is performed.</p>\n<p>The following code checks the input values.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token comment\">// do the work</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>InputBufferLength <span class=\"token operator\">&lt;</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>ThreadData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\tstatus <span class=\"token operator\">=</span> STATUS_BUFFER_TOO_SMALL<span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">auto</span> data <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>ThreadData<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>stack<span class=\"token operator\">-></span>Parameters<span class=\"token punctuation\">.</span>DeviceIoControl<span class=\"token punctuation\">.</span>Type3InputBuffer<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data <span class=\"token operator\">==</span> nullptr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">&lt;</span> <span class=\"token number\">1</span> <span class=\"token operator\">||</span> data<span class=\"token operator\">-></span>Priority <span class=\"token operator\">></span> <span class=\"token number\">31</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\tstatus <span class=\"token operator\">=</span> STATUS_INVALID_PARAMETER<span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This time, because the goal is ultimately to set a thread’s priority, the passed buffer needs to store <code class=\"language-text\">ThreadData</code>.</p>\n<p>That is why the size of <code class=\"language-text\">stack->Parameters.DeviceIoControl.InputBufferLength</code> is checked.</p>\n<p>After checking the size, the buffer in the stack location is cast to <code class=\"language-text\">ThreadData</code> with <code class=\"language-text\">(ThreadData*)stack->Parameters.DeviceIoControl.Type3InputBuffer</code>.</p>\n<p>If it turns out to be a null pointer, an error is returned.</p>\n<p>Finally, it checks whether the <code class=\"language-text\">Priority</code> value in <code class=\"language-text\">ThreadData</code> falls within the prescribed range.</p>\n<p>Once validation of the passed data is complete, the thread priority is set with the <code class=\"language-text\">KeSetPriorityThread</code> function.</p>\n<p>The <code class=\"language-text\">KeSetPriorityThread</code> function needs to receive, as its first argument, a pointer to the thread whose priority is to be set.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kesetprioritythread\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">KeSetPriorityThread function (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>Therefore, the <code class=\"language-text\">PsLookupThreadByThreadId</code> function is used to obtain a pointer to the thread object from the passed thread ID.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-pslookupthreadbythreadid\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PsLookupThreadByThreadId function (ntifs.h) - Windows drivers | Microsoft Docs</a></p>\n<p><code class=\"language-text\">PsLookupThreadByThreadId</code> can be used by including <code class=\"language-text\">ntifs.h</code>.</p>\n<p>To avoid compile errors, <code class=\"language-text\">ntifs.h</code> needs to be included before <code class=\"language-text\">ntddk.h</code>.</p>\n<p>Let’s look at the code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">PETHREAD Thread<span class=\"token punctuation\">;</span>\nstatus <span class=\"token operator\">=</span> <span class=\"token function\">PsLookupThreadByThreadId</span><span class=\"token punctuation\">(</span><span class=\"token function\">ULongToHandle</span><span class=\"token punctuation\">(</span>data<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">NT_SUCCESS</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">KeSetPriorityThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>PKTHREAD<span class=\"token punctuation\">)</span>Thread<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">ObDereferenceObject</span><span class=\"token punctuation\">(</span>Thread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">KdPrint</span><span class=\"token punctuation\">(</span>\n    <span class=\"token punctuation\">(</span><span class=\"token string\">\"Thread Priority change for %d to %d succeeded!\\n\"</span><span class=\"token punctuation\">,</span>\n      data<span class=\"token operator\">-></span>ThreadId<span class=\"token punctuation\">,</span> data<span class=\"token operator\">-></span>Priority\n    <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>After setting the priority, the <code class=\"language-text\">ObDereferenceObject</code> macro is called.</p>\n<p>This macro decrements the reference count of the object passed as an argument, but I did not quite understand what it was for.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-obdereferenceobject\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ObDereferenceObject macro (wdm.h) - Windows drivers | Microsoft Docs</a></p>\n<p>A reference count seems to be a count of how many references or pointers to that object exist within the system.</p>\n<p>If the reference count is 0, the system (perhaps GC or something similar) is allowed to destroy it.</p>\n<p>Reference: <a href=\"https://ja.wikipedia.org/wiki/%E5%8F%82%E7%85%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Reference counting - Wikipedia</a></p>\n<p>The reason <code class=\"language-text\">ObDereferenceObject</code> decrements the reference count here is to prevent leaks in the system.</p>\n<p><code class=\"language-text\">PsLookupThreadByThreadId</code> increments the reference count for the thread it receives.</p>\n<p>Therefore, if it is not decremented by <code class=\"language-text\">ObDereferenceObject</code> before the routine finishes, the reference count remains increased and a leak occurs.</p>\n<p>With that, I was able to trace through the kernel driver implementation more or less all the way through.</p>\n<p>I will omit the client implementation in this article.</p>\n<p>If you want to dig into it in more detail, please purchase <a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a>.</p>\n<h2 id=\"installing-the-driver\" style=\"position:relative;\"><a href=\"#installing-the-driver\" aria-label=\"installing the driver permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Installing the driver</h2>\n<p>As in the previous article, install the created driver into the system using the same procedure.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">$ <span class=\"token function\">sc</span> create second <span class=\"token function\">type</span>= kernel binPath= C:\\Driver\\SecondDriver\\SecondDriver<span class=\"token punctuation\">.</span>sys\n<span class=\"token namespace\">[SC]</span> CreateService SUCCESS\n\n$ <span class=\"token function\">sc</span> <span class=\"token function\">start</span> second\nSERVICE_NAME: second\n        <span class=\"token function\">TYPE</span>               : 1  KERNEL_DRIVER\n        STATE              : 4  RUNNING\n                                <span class=\"token punctuation\">(</span>STOPPABLE<span class=\"token punctuation\">,</span> NOT_PAUSABLE<span class=\"token punctuation\">,</span> IGNORES_SHUTDOWN<span class=\"token punctuation\">)</span>\n        WIN32_EXIT_CODE    : 0  <span class=\"token punctuation\">(</span>0x0<span class=\"token punctuation\">)</span>\n        SERVICE_EXIT_CODE  : 0  <span class=\"token punctuation\">(</span>0x0<span class=\"token punctuation\">)</span>\n        CHECKPOINT         : 0x0\n        WAIT_HINT          : 0x0\n        PID                : 0\n        FLAGS              :</code></pre></div>\n<p>After this, if you check <code class=\"language-text\">GLOBAL??</code> in <code class=\"language-text\">WinObj</code>, you can confirm that the symbolic link for the <code class=\"language-text\">SecondDriver</code> you created exists.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/11cd136e5be9b88c1e7f11fa9ff10614/0b533/image-21.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 74.16666666666667%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAARlAAAEZQAGA43XUAAACJUlEQVQ4y5WUCY+iQBCF+f9/bbJHdjMqKF4Icsh9CYpv69XYhtlsJtlOKqSb5utXr6qx4qxC29So6xpN06CqZN52mKYJ9/sdt9vty+A+Mx6PByw3OCMrY6TpBVmawfd9hOcQQRAgiuLXQX8HD87zAlmWKXgYBhEwweqrPdJ4h7rp9GUcxxoEt22L67VH13X/DL7fbDbY7/a4XC6q0hrbAIf1G4qyVZVU1IoCquUBZVliHEdVMA+ztt1uFfoC3roA3vYHmnbQE5nOcL0KLFelBNNLBj0y3hp/CfNPvqSfywEjrGmIsHPeEMWZwqgoFxjhxmgGAX3fq7L5muu6EhuEUaRz636VAhx+I0kKSbdCJcC6+ijEVZRSET+mmrIo9UCzRgAVLpdLJCble3/WlPO8ViBBVBGGkao0agjJ0lRTI4iDT8dxsFgsECfJsyidj6P7XWC9wGoURaEgFsb0mAHO4SbWzvpDYfJUOEiV/cMv5EUj/XeWlCR16bFIFLIPz7LGnqRqAzeDQHrItHMRosBpGjEOvU7YMpX4p+mwWcVDFoLxUvh8mmqzbdabNTKxQoGYDXY/of8zCKTKSKrMLCzji1HIBu26VuHzaORdnJVwjiHcIFUrPM+Dbds47Pd6W+i/NfeFFV6tVtjLBvoWhuGn8OWOv9sbfPv5Lqq2uo/A0+mkQlThHMj7aduO3JDkedk//224ryxyrGVPXTf6DVU6MveOngL/AA+cfmoXU3IpAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/11cd136e5be9b88c1e7f11fa9ff10614/8ac56/image-21.webp 240w,\n/static/11cd136e5be9b88c1e7f11fa9ff10614/d3be9/image-21.webp 480w,\n/static/11cd136e5be9b88c1e7f11fa9ff10614/b0a15/image-21.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/11cd136e5be9b88c1e7f11fa9ff10614/8ff5a/image-21.png 240w,\n/static/11cd136e5be9b88c1e7f11fa9ff10614/e85cb/image-21.png 480w,\n/static/11cd136e5be9b88c1e7f11fa9ff10614/0b533/image-21.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/11cd136e5be9b88c1e7f11fa9ff10614/0b533/image-21.png\"\n            alt=\"image-21.png\"\n            title=\"image-21.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Now that the driver has been installed, let’s try setting a thread’s priority with the client application.</p>\n<p>This time, for verification, I decided to manipulate a Notepad thread.</p>\n<p>From Proexp, you can see that the Notepad thread’s priority is set to 10.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 554px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/87f9871280c443cd79688290c6f4679e/04abd/image-22.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 115.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD/0lEQVQ4y51VWW8bVRSev4yExBu8wBu80AfUNwQPPLRpgUqJEzduHbUpjp3W9tgzXmbfN8/qNfb449wxCUGtIOLI13eZud/5zjrcelei2+5hePQU0vExgqkEfzKBrSowHBO+Z0BXJ3AsDas8Qeg5SFwHqa7DGA5hj0Zwx2N4kgTp8hLchgCHXR6jkxeQ6mcIoxlM14XregiCEJblwDJtFPMFFssV4iRBmuVI8wLbskRO5wHdYcQsIsKttzsIoym06w6mVy1kcYzRaAyTgNjFducaE0mG6/no80NMyAJBHKHVakNRNdi2g3a7A1UzYCsKOCeM0TlvYFKvQW82MScGyyLFfrMAsAUtaN4BJc3bJa33f+9vVof1dl2dK4MBuClpcS0Tq8WiYhfMErT1Ag0xRI33cdL38OK9hedXGl5PM/zWMfDsSkWNzpuij9MPOi7lBCN/BZ98yw2nUzJBhGXbiKIQUZLjlz8M/PjWwK/iAkd8jqNBgWc07tbDAk/7GX6o8fj+9w4eHffRGEWIAg+cTY4XKVKGYVAQAhR5TuyZqTf4LynJLdtljnI9J8tv4DjEUJRl6KaJzXaLxeoQxf2tp8r9v477sqMo2wxQljWofR4JMVxSJLM0w57e3dPf7bgvt/t/PKex3e0QMMCmIeIRsfwpmeHnOIJHDKsL+BjsU1KBVvaX6FgWuCfda3x20sXndQFfnAuwKI3uM3gIYLk/OOl8IIOT7BRvzmS06z4+NGeYRelfL+LBgKh+JaYimRyEFlrvFdQaFuqvTEqd7CMfPWSQzRgKZHIYBaidXuDJ8z5qZyrCMMX/lcHAoNKLU5y+fId6vYWLix4xjLHZbLBar7GlOmfr9XpDabEjv5fVXBQFZrMZzXPklLcRNYcVpZw4Ih8W8zmSNEaWJZSYFmIqP03TqXKcSmuWZXBovSYFaZpiSd0ljiKMqboC34dNOczzlHaUHTZVG+d5HhZUx4yJROnj096y7OqMCZtVRYVGNT+hvucQm3CxREyMdofWcCesfLlut1shM3MUaj8+aTVNi4D9O0BFUirAkvb56yaEL7+C8PU3CB4/hvXtd4jfvK3eHVMJc4wus58JA6yaKgGahkkmZpWPWLPNqTcyWVJFKWcvoTZeIe/1MWtdISFlTCaswfZ6PWJkVgcj0hCGYQXAfMv8tlwu4BFbBs5kQ5bofgjDDxCT6fczVSaXcYIgVIuIHM3YMsd/Slg3YsrZnFGJGvTNicMAlqGD7x/uVYCqqt5dEilyjCFzAfPd/cGizZQmSQrNnUFQbMh2BJfY6ppGaRRXFlYMbyPd7/crLS59pCwqdBas28F6HTtnLaotqGhc8XjHyxhLKq47HQiCWFn4J+DUtzkoTpmRAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/87f9871280c443cd79688290c6f4679e/8ac56/image-22.webp 240w,\n/static/87f9871280c443cd79688290c6f4679e/d3be9/image-22.webp 480w,\n/static/87f9871280c443cd79688290c6f4679e/5e3e0/image-22.webp 554w\"\n              sizes=\"(max-width: 554px) 100vw, 554px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/87f9871280c443cd79688290c6f4679e/8ff5a/image-22.png 240w,\n/static/87f9871280c443cd79688290c6f4679e/e85cb/image-22.png 480w,\n/static/87f9871280c443cd79688290c6f4679e/04abd/image-22.png 554w\"\n            sizes=\"(max-width: 554px) 100vw, 554px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/87f9871280c443cd79688290c6f4679e/04abd/image-22.png\"\n            alt=\"image-22.png\"\n            title=\"image-22.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Let’s set this thread to the maximum priority, 31.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">C:\\Driver\\SecondDriverClient<span class=\"token punctuation\">.</span>exe 8616 31</code></pre></div>\n<p>After the application finishes executing, the Notepad thread’s priority changes to 31 as shown below.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/590aec4f72437db74fea11a1a8190b43/0b533/image-23.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 73.75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAARlAAAEZQAGA43XUAAACGElEQVQ4y41UyW7aUBQ1IKGUn2EDUrpJJSS+gR3iY1inq4Ao/YAki+YbElA2CClpWiExKHbAE3gMNmCwOb3vpaG0JYErHb/B9x7f0cJYVWFbFkzT4PC8KVzHxrNtw3NdOKYJlyA1mlBub6E0mwgHAzBZr9fsgW0RGKFhWtB1HaqqQdNe1sdHkT5gQVYUqIoK8eYGo0YDw+trhP3+24TGZAKFjAzDICIVEzqPx2Mi1iBJEr9zyFtHeoIvy/BGI0QUESPbBUEnY0kUYZESIzUpPAZG3G630Wq1uPchDhMhCIK9Sp7ncS+Z7mI+R7BY8P2/WC6XEHxSYBLtcH+1WvF3366ucHLyCfl8HrlcDh+Pj5HNZjkymcxmTafTECxvtknwW4Rf6nUIgoBUKoVkMokPR0dIJBL87j9Mp/O9hLVabUMYi8U2xmz/emZrPB5nhH88/Eu2CM/OKtyIG+zyahu6PoZtO5ToAI7jwvd8eL4PjaqsU9W92Qynp58PJ5RHMhHaiMIIIjXzkPpMfxpC+vETJrUTogjVavVwQta4bDJ88kqVFd5v07t7dOtfoV1eAt0uar+LchAha+L5bM57yKHQ2dlynzGkEZzQLDOpVF5yyCrMqvsehBnlKKKwwjAk0gAyjZdJudNp9GQKn+3L5fJ+z17R6XQwoL9HnwaeQaS89bo9PHx/QK/X47N8fn6BQqGAUqmEYrH4Ln4Bvx1oDKTeWugAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/590aec4f72437db74fea11a1a8190b43/8ac56/image-23.webp 240w,\n/static/590aec4f72437db74fea11a1a8190b43/d3be9/image-23.webp 480w,\n/static/590aec4f72437db74fea11a1a8190b43/b0a15/image-23.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/590aec4f72437db74fea11a1a8190b43/8ff5a/image-23.png 240w,\n/static/590aec4f72437db74fea11a1a8190b43/e85cb/image-23.png 480w,\n/static/590aec4f72437db74fea11a1a8190b43/0b533/image-23.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/590aec4f72437db74fea11a1a8190b43/0b533/image-23.png\"\n            alt=\"image-23.png\"\n            title=\"image-23.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<h2 id=\"checking-the-behavior-with-kernel-debugging\" style=\"position:relative;\"><a href=\"#checking-the-behavior-with-kernel-debugging\" aria-label=\"checking the behavior with kernel debugging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Checking the behavior with kernel debugging</h2>\n<p>Now, this has taken quite a while, but at last we are finally getting to the main point.</p>\n<p>I want to perform kernel debugging from WinDbg and observe the behavior of the kernel driver I wrote.</p>\n<p>I have already introduced how to configure kernel debugging before, so I will omit it here.</p>\n<p>Reference: <a href=\"/windows-windbg-004-kernel-debug\">First steps for kernel debugging a Windows 10 environment with WinDbg</a></p>\n<p>Reference: <a href=\"/windows-windriver-001-tutorial-en\">Writing a Windows kernel driver from scratch and analyzing it with WinDbg</a></p>\n<h3 id=\"setting-a-breakpoint\" style=\"position:relative;\"><a href=\"#setting-a-breakpoint\" aria-label=\"setting a breakpoint permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting a breakpoint</h3>\n<p>First, after preparing kernel debugging, confirm that the <code class=\"language-text\">SecondDriver</code> module is loaded.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">kd> lmDvmSecondDriver\nBrowse full module list\n<span class=\"token function\">start</span>             <span class=\"token keyword\">end</span>                 module name\nfffff801`18390000 fffff801`18397000   SecondDriver   <span class=\"token punctuation\">(</span>deferred<span class=\"token punctuation\">)</span>             \n    Image path: \\??\\C:\\Driver\\SecondDriver\\SecondDriver<span class=\"token punctuation\">.</span>sys\n    Image name: SecondDriver<span class=\"token punctuation\">.</span>sys\n    Browse all global symbols  functions  <span class=\"token keyword\">data</span>\n    Timestamp:        Sat Jan 29 20:08:51 2022 <span class=\"token punctuation\">(</span>61F52043<span class=\"token punctuation\">)</span>\n    CheckSum:         0000EB8D\n    ImageSize:        00007000\n    Translations:     0000<span class=\"token punctuation\">.</span>04b0 0000<span class=\"token punctuation\">.</span>04e4 0409<span class=\"token punctuation\">.</span>04b0 0409<span class=\"token punctuation\">.</span>04e4\n    Information <span class=\"token keyword\">from</span> resource tables:</code></pre></div>\n<p>As we have seen from the source code so far, the routine that receives IRPs from the client and actually changes the priority is <code class=\"language-text\">SecondDriverDeviceControl</code>.</p>\n<p>For that reason, with a breakpoint set on <code class=\"language-text\">SecondDriverDeviceControl</code>, perform the priority change from the client application.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">kd> bu SecondDriver!SecondDriverDeviceControl\nkd> bl\n     0 e Disable Clear  fffff801`18391040  <span class=\"token namespace\">[G:\\Try2WinDbg\\drivers\\SecondDriverSample\\SecondDriver\\SecondDriver.cpp @ 18]</span>     0001 <span class=\"token punctuation\">(</span>0001<span class=\"token punctuation\">)</span> SecondDriver!SecondDriverDeviceControl</code></pre></div>\n<p>As before, start Notepad and then issue a request from the client application to change the Notepad thread priority to 31.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">C:\\Driver\\SecondDriverClient<span class=\"token punctuation\">.</span>exe 8520 31</code></pre></div>\n<h3 id=\"analyzing-irps\" style=\"position:relative;\"><a href=\"#analyzing-irps\" aria-label=\"analyzing irps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Analyzing IRPs</h3>\n<p>This time I also opened the source window.</p>\n<p>It is very convenient because when execution stops at a breakpoint, you can immediately see which line of the source code it is on.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 932px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/821532881aff984b5d35308ef816777d/f6f78/image-24.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 93.75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAADWUlEQVQ4y41U2W4jNxCcL88X5Cm/k7dkN8FaWh/yWrJkaWRJc5+c+55KNSUHxgIBQqDQlEg2q7qLY/z2p4Vf/3Dwy+8XfDmkyPIaQVrBTwp4cc55qRGqCm6UYbc/Y7lcYfW8RRSlOJ0uGmEYw/NCGGXdoO9auJYsHGEe32E5DmHD9Tw0XYdpnjW6foDKChwOJtYvG5zez3h+fsEPzo+cO44HIy0rVA0QRh1vVIhChboeMI7Q+DymaSaTDL7fEBUsK4XjKgRBA6VGVBVgxHEC33tC4P4F1/4bgX+HLH1ElhDxE/GIQq1QZU9oa5csIry9XWCaNvZ7h3MP+0OI4zGmwoAM8xx5WeB4NuH4O8Yf2JmPuNhbFLkPldioyhDjkGHoa9i2h91uj/3bHpuNidXqjO3WxcGM8W46MDLyrFtKDibSZhP8mBIiJLHSRW+a7oYeXdfrkvg+GxWwaV5L2YDtEDYon5LTokI/TsiLGn7swfIsJmLCJEYcxyiKAiUVSKx4uWO7ZLjF6+sL2Z2wWJZYr1t2vcXD9wFGkpcYpIvsgB/mtE3OwywDY5ZlbFCNYRhuGHE+W7TNEg8Pj7i7W2CxWLLr4g4Tr2vrynBkwqaemYAdZ8vTNGcsNaOczCSp/K5psTM9t1gscH9/r3H37RtL4FP6hTXcw1C3hG078U+RWbE2qWanVKalTtNEC31iqBN+J8t7fP36BevNhl038U4Pa4Yiue8GyixRsF5NU2tWIrssSjajY8IR3MbLAnZ1i836jdEkdpR8oG2OvOxyqyENOxNxUmvJZVlqZmma6jhLJsza2Emq4LoeLpecUlvuKWj2gF33eVl8TThxuxyMaHJJIrUTVh/NaNtW/xbbWJbD7q5o6h0lHmjmEy9wdR0Vzxox3+bAGhVFo51u0xZym1Lq1oxKo2kaHUWyR4ZhGPGF+Xoury1JrmQMy3K1gaMo4ULORAVvyrkh46FExywrNaT7tu3rr0qeV7rmAlmTfXHMhEVxtYNACi9RujnS7DLv+6vsru14WOqqdJQ9svYZNZ+cEYShlvIxxC5ibJEotRPLyOj7ns/S17Uef/4M3YZcYgw/LUoCYSSHrgfnf9ek2/M84b+G7DfyTOqlUFZXywiE+kcZPv77Pyjo6X8AsbaeA26Sb2AAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/821532881aff984b5d35308ef816777d/8ac56/image-24.webp 240w,\n/static/821532881aff984b5d35308ef816777d/d3be9/image-24.webp 480w,\n/static/821532881aff984b5d35308ef816777d/3b46e/image-24.webp 932w\"\n              sizes=\"(max-width: 932px) 100vw, 932px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/821532881aff984b5d35308ef816777d/8ff5a/image-24.png 240w,\n/static/821532881aff984b5d35308ef816777d/e85cb/image-24.png 480w,\n/static/821532881aff984b5d35308ef816777d/f6f78/image-24.png 932w\"\n            sizes=\"(max-width: 932px) 100vw, 932px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/821532881aff984b5d35308ef816777d/f6f78/image-24.png\"\n            alt=\"image-24.png\"\n            title=\"image-24.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>The source window is extremely useful, and it also lets you set additional breakpoints directly from the source code.</p>\n<p>This time I want to inspect the IRP information received from the client application, so I set a breakpoint on the line immediately after the stack location is obtained.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 565px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/e832e3c4755d1dba113b7cb74dd97190/07eba/image-25.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 77.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACnklEQVQ4y51SaWvcMBDd//9bCik0NNC0C0lp6UELSWC76+2uL61vr23Zsny/jrQHaUL6oQPDjEbS6L2nmaWej4hzuNYXuOZnBOw77M0nbI1b+O43VPkSNTcgyUWxAs+WkJWBkupNtUZdriD4iuISY59jlrAdwiJD4t/AMC5gsktsnUtYuyssrVfYum+wti9gOK/hs2v4zjVi7wM8ivtwjjy+0Z5Fc/SNj1lkOciaHsp+2ykebr/i/t0NFu8/4ufVHHfXt3ig/MfbOUIWo5IDOG9RVR1y3uCpzSLTRiJoYxrpkES0ceH/WsK9u4e/XMFbLBGu1gioVuUZmrZBXQu0jYSUAkJU2mvycRwxK0SNQraYpgmODYRJhyhNESQpGOlrMxfObocgjmFaFsliIAhDlGWJnB7gpL+KRVFgGKhhlhcIy5oQTvRSh5JeSnmCOI8R7gPUhKJrO/R9j77r0PU9XjIFapYXXCM8WcF7+JEHL2LYBQyWbSEIAnieB9/3Ke6wI8T7/R5JktBeiJQYRVGkIyHkB4Rk4zjRMwBjJVariHRq9SF1MSbKqolaq1wIoTVTrpANw6BdI0yEPDYcqdgec/yX6Yb5kbJ6ybQ5HNcjNDEJLeC6KSyLISFkGSEs8hxZliEMD1RThfrIQDHRDeNKnhtWJbBe29hsTLogsFiE2G4OusVxpLVkjCGmyyeaJ1cf9wwhMNA8gkQejiSUTofDyg+yDDq+SPkxwroeaGBrtK2kvKZc6vlSey2NTUMD3dBnqXrbtto7qv81Nll9Qgj6WfXLHhyHaX1M0zyOjU96unptbk2d19RU1lI3PzdUgx1wcSBHhWkaSLuRmkrKR01ToWiaRiNRKNW6H4ZnQ32mXDzScHhy8F82aQDTuZmKfwBc9sV5X3o0CgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/e832e3c4755d1dba113b7cb74dd97190/8ac56/image-25.webp 240w,\n/static/e832e3c4755d1dba113b7cb74dd97190/d3be9/image-25.webp 480w,\n/static/e832e3c4755d1dba113b7cb74dd97190/acb73/image-25.webp 565w\"\n              sizes=\"(max-width: 565px) 100vw, 565px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/e832e3c4755d1dba113b7cb74dd97190/8ff5a/image-25.png 240w,\n/static/e832e3c4755d1dba113b7cb74dd97190/e85cb/image-25.png 480w,\n/static/e832e3c4755d1dba113b7cb74dd97190/07eba/image-25.png 565w\"\n            sizes=\"(max-width: 565px) 100vw, 565px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/e832e3c4755d1dba113b7cb74dd97190/07eba/image-25.png\"\n            alt=\"image-25.png\"\n            title=\"image-25.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>This time, to do something a little different from before, I decided to analyze it mainly through the GUI.</p>\n<p>Once execution reaches the line immediately after the stack location is obtained, inspect the stack location information in the Locals window.</p>\n<p>In WinDbg’s GUI, the structure information can be formatted and inspected like this.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 899px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/dd5b748009f59f5d831aa65ca2a4850a/681f1/image-26.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 45.833333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZUlEQVQoz3WQ/U6DMBTF9/5/G+O2zBgTE9/CxGzTJe4J/JoDyvimhQKDwrG9yIIzNjk0vYf76+md3G8Zrjcu5msLNy8eFhuG6WqPmdZ8bVP94uEN06U+P9lUm60sLJ77vqvlFy4fP3G79XG39TCppYAIXSjJYVZbCPCAoUgClGlIqniESvSCKnuhAfcZYtc69QKdBtYNbOYi4UIfAS4y1E37Y/eii4y6fjc1pT+v7x9w/YB8pU3VaaCUBRzHQS5zMsqyBOcceZ6jqiocj0eqKaX6S3TTIOYw2LaNtm1P3sQ07XY7uK6rjQ48TbG39ojimIBG50BKrCGMMXieB6FfJXPZA02SVEOGH7Msw8E7INZAKSWKoqD9HGj2IAgQhiHquiafgHGcIIoieqIpmISWZZ0uGWsMNACTMEkS6i306AjIhaAnDcsk8n2fEpq5mnQmddM0fxIOs/41w/Fh+Pm/dZ5yXB/0DZlCsRg+O4h1AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/dd5b748009f59f5d831aa65ca2a4850a/8ac56/image-26.webp 240w,\n/static/dd5b748009f59f5d831aa65ca2a4850a/d3be9/image-26.webp 480w,\n/static/dd5b748009f59f5d831aa65ca2a4850a/8bcb7/image-26.webp 899w\"\n              sizes=\"(max-width: 899px) 100vw, 899px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/dd5b748009f59f5d831aa65ca2a4850a/8ff5a/image-26.png 240w,\n/static/dd5b748009f59f5d831aa65ca2a4850a/e85cb/image-26.png 480w,\n/static/dd5b748009f59f5d831aa65ca2a4850a/681f1/image-26.png 899w\"\n            sizes=\"(max-width: 899px) 100vw, 899px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/dd5b748009f59f5d831aa65ca2a4850a/681f1/image-26.png\"\n            alt=\"image-26.png\"\n            title=\"image-26.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>The arguments passed from the application are stored in the input buffer of the IRP passed to the device control routine.</p>\n<p>If you inspect the location pointed to by the input buffer, you can see that it is <code class=\"language-text\">0x1cefd9f6d8</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 309px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/2b706ba164031ccb8f6aa1e71b152317/532e8/image-27.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaElEQVQoz51Sa3OCMBDk//+6dqYqIEkgQVTeCFYewvYSi6XUT72ZnUnC3XK7d9bnrUVZXdDUNeI4Rl4UBhMeMU2TwfL8fX2+L8O6NFdIFSIIAgOfIKVEQ+/DMDwT18WvyAzhre2QpClCIlFKGTIpFVzHRVlWGMcR9/vdJM/nZYdrYmu+5nkGxgR8weExD77vQx0i2LaNlH6ooyhyCCFwH6eF/N92WPNDQYQ+JXPG4bp7yPAAxpnBHFVZGgVr6Uv8EGYZBBdQRKS91J2cz2cjc86pqhLbzQZMBAhVgOh4+uth13VUMOJ0OmG/38NxHXDOSeoOu52N6lKj7ztCjzRJqHvHKHh/f8PHZktWFTS8Hm3bQnNZNU2zIClKSdiOA+a5ROwaqXo4GRVosq7ryZacujricAiNGuZ5iJMUQ/8g1LCqujF+Sb0utD6aWPuUkgX/CSK8Gt886sqhVeE03SiKnmuyNn2JV9+/AHrb/uPrOEYXAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/2b706ba164031ccb8f6aa1e71b152317/8ac56/image-27.webp 240w,\n/static/2b706ba164031ccb8f6aa1e71b152317/451be/image-27.webp 309w\"\n              sizes=\"(max-width: 309px) 100vw, 309px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/2b706ba164031ccb8f6aa1e71b152317/8ff5a/image-27.png 240w,\n/static/2b706ba164031ccb8f6aa1e71b152317/532e8/image-27.png 309w\"\n            sizes=\"(max-width: 309px) 100vw, 309px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/2b706ba164031ccb8f6aa1e71b152317/532e8/image-27.png\"\n            alt=\"image-27.png\"\n            title=\"image-27.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>So, let’s look at the values stored at that referenced address in the Memory window.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 403px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/321e106c693079f7889192779df1e18a/045fd/image-28.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 96.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAADfklEQVQ4y1VUy44iNxTlW7LJcr4hi/xdlMVEihQpUTSfMYtITTfh2VBV1NvlerseUBQ0dAMzPZo5uXYBPUG6cvnaPj73nmN6TbNDXTUQeQXGQoQ8UfP9bo+oaPFhXOCvYY7f7zO8v8vwWz+DFjV4ftqj3Txh2/4/eqvVBq4fQWMCMzfFo1/AKQ4I6wM+Ohv8/DfHT38yvHvv4IdfTPz4q4U/hiWSeg8z28HJu7ApXEGAL8/PSFOBdrtD27bYPB0RiTXCtISoWxRFiSwrcDqdcf19+gK8fP6G42s3XmN//ore6+sXbLcHZElM5QZYbzYoqwpRnGC1brBqGmSiQEXfTbvF4eWI4+mE7W6HzXaLl+OR4oT94UD5cwfYtntM5xb+6U8xmtkYzyw8DHUMpzblPQxGSwzGMgz0/9XVqOYjg/Y6GD86t7F3otvqusFCd9AfzDCRi1PaPNQw0zxoywBz3YducugWx9xgKmdYIQw7VPNHWp/rjPb76B2JsgQ09AXu7/uIqXTOXFiWhaoq0TQrNdZ1iVVdqXG9qlGIHEJkKAuBshSoKGpa752o/hUBuo6D2WyGJM1UL13Xp16WJEpBuRRplpE4GQmYIs9zRFFMERGBhIBztU+I8g1Q1xbo9/vgYQzmuTAME7kQSOiA7/tgQYA47kAksMy5rgvOOQJa4xSO670BOraFyWSi1OWBD9t2kRGTuq4VqAxpoYoc0JDyEpiH9BAosixVzIvyu5KXBik3GCCkUgLmwTRttamkTTFdIkvMMiqNLLSiHgYBp5fFVEhQTm0KePgGaBPDMTGUPYzCgOaOYiPLkwckwyiOVNkxgYcXdh0YV6PvszdA01xiOBophsx3MZ8vqOQMOQHKA4L6eRXkmpO9C0NOF0RKOHn2BmjoGtnmnpIJwoBhsdCUsvJwFEYXNpEqWxCoLFWJxXz1Hcn17wFdh17FdEY2SGmRE2MLgqxQlqUSIKG8LL+45TrFVRCYZBkQazJ2B6gt5ri7u1ON9Vwbo/FEbUhIEIc86nnehREj0ZiaS9t4ZLFu9GBR32+Ajm1jMp3eGC6XJv0p5IqNEoJC9kmy7Ix9aUPUCSPnLLgwlE/PXHa2kT6UPdQ1Q5WcU8+kAFfPKWBSnLHgZhvFms4oY5/Pn7Bet0qUh4cHdYvvOdA0nRglShRpB/9ykNO6BL2Kcg05l4D/AZt2VHCOZCKvAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/321e106c693079f7889192779df1e18a/8ac56/image-28.webp 240w,\n/static/321e106c693079f7889192779df1e18a/ca1b5/image-28.webp 403w\"\n              sizes=\"(max-width: 403px) 100vw, 403px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/321e106c693079f7889192779df1e18a/8ff5a/image-28.png 240w,\n/static/321e106c693079f7889192779df1e18a/045fd/image-28.png 403w\"\n            sizes=\"(max-width: 403px) 100vw, 403px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/321e106c693079f7889192779df1e18a/045fd/image-28.png\"\n            alt=\"image-28.png\"\n            title=\"image-28.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>In the client application, the received arguments are converted into numeric values with the <code class=\"language-text\">atoi</code> function and then passed to the driver routine as follows.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">data<span class=\"token punctuation\">.</span>ThreadId <span class=\"token operator\">=</span> <span class=\"token function\">atoi</span><span class=\"token punctuation\">(</span>argv<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ndata<span class=\"token punctuation\">.</span>Priority <span class=\"token operator\">=</span> <span class=\"token function\">atoi</span><span class=\"token punctuation\">(</span>argv<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The C++ <code class=\"language-text\">atoi</code> function converts a string into a 4-byte <code class=\"language-text\">int</code> value.</p>\n<p>Therefore, it seems best to read the data stored in memory in little-endian format, 4 bytes at a time.</p>\n<p>From the above, we can see that the values stored in the memory pointed to by the input buffer match the arguments given to the client application, as follows.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">0x2148 = 8520\n0x1F = 31</code></pre></div>\n<p>WinDbg makes it very easy to inspect the IRP information passed to a kernel driver, which is extremely convenient.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>Now I have been able to get an introductory look at implementing a kernel driver with the minimum necessary functionality, as well as analyzing IRPs through debugging.</p>\n<p>There is still a long way to go, but I plan to keep studying kernel programming and debugging.</p>\n<h2 id=\"reference-books\" style=\"position:relative;\"><a href=\"#reference-books\" aria-label=\"reference books permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reference books</h2>\n<ul>\n<li><a href=\"https://amzn.to/3H3WMoe\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows Kernel Driver Programming</a></li>\n</ul>","fields":{"slug":"/windows-windriver-002-irp-en","tagSlugs":["/tag/win-dbg/","/tag/kernel/","/tag/kernel-driver/","/tag/reversing/","/tag/english/"]},"frontmatter":{"date":"2022-01-29","description":"","tags":["WinDbg","Kernel","KernelDriver","Reversing","English"],"title":"Writing a Windows Kernel Driver from Scratch and Inspecting IRP Requests with WinDbg","socialImage":{"publicURL":"/static/d540acb87fd7fe1b60f3feef78deb15c/windows-windriver-002-irp.png"}}}},"pageContext":{"slug":"/windows-windriver-002-irp-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}