{"componentChunkName":"component---src-templates-post-template-js","path":"/a-part-of-anti-virus-3-03-en","result":{"data":{"markdownRemark":{"id":"ed67250b-0691-5b22-978d-db30ebcde2da","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/a-part-of-anti-virus-3-03\">original page</a>.</p>\n</blockquote>\n<p>In the previous chapter, I explained a simple user-mode program that registers WFP filters and blocks or permits communication.</p>\n<p>Next, I will explain WFP Callout drivers, which are also widely used in software such as antivirus products and EDR.</p>\n<p>Several sample programs for WFP Callout drivers are published in the official Windows-driver-samples repository under <code class=\"language-text\">./network/trans/</code>.</p>\n<p>In particular, the inspect sample published in that repository implements the basic functionality of traffic inspection with a WFP Callout driver, and can be regarded as one sample that is close to how antivirus products and EDR use WFP.</p>\n<p>However, that sample program is implemented in roughly 3,000 lines of code, and it is a bit too complex to explain step by step starting from an overview of WFP Callout drivers.</p>\n<p>So, in this chapter, I will use a simple kernel-driver sample, created with reference to the official sample code above, that has the minimum functionality needed to understand basic traffic processing with a Callout driver.</p>\n<p>The sample program explained in this chapter can also be downloaded from the following repository.</p>\n<p>URL: <a href=\"https://github.com/kash1064/book06-wfp-samples\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://github.com/kash1064/book06-wfp-samples</a></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=\"#overview-of-the-sample-program\">Overview of the Sample Program</a></p>\n<ul>\n<li><a href=\"#running-the-sample-program\">Running the Sample Program</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#about-the-sample-program-implementation\">About the Sample Program Implementation</a></p>\n<ul>\n<li><a href=\"#registering-the-driver\">Registering the Driver</a></li>\n<li><a href=\"#registering-callout-functions\">Registering Callout Functions</a></li>\n<li><a href=\"#the-classification-callout-function-registered-in-classifyfn\">The Classification Callout Function Registered in classifyFn</a></li>\n<li><a href=\"#the-event-notification-callout-function-registered-in-notifyfn\">The Event Notification Callout Function Registered in notifyFn</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#controlling-traffic-by-coordinating-the-callout-driver-with-a-user-mode-program\">Controlling Traffic by Coordinating the Callout Driver with a User-Mode Program</a></p>\n<ul>\n<li><a href=\"#coordination-between-the-callout-driver-and-the-user-mode-program\">Coordination Between the Callout Driver and the User-Mode Program</a></li>\n<li><a href=\"#suspending-classification-in-the-sample-program\">Suspending Classification in the Sample Program</a></li>\n<li><a href=\"#processing-ioctls\">Processing IOCTLs</a></li>\n<li><a href=\"#performing-traffic-classification\">Performing Traffic Classification</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n<li><a href=\"#afterword\">Afterword</a></li>\n<li><a href=\"#table-of-contents-for-this-book\">Table of Contents for This Book</a></li>\n</ul>\n<h2 id=\"overview-of-the-sample-program\" style=\"position:relative;\"><a href=\"#overview-of-the-sample-program\" aria-label=\"overview of the sample program 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>Overview of the Sample Program</h2>\n<p>The sample program explained in this chapter is a relatively simple Callout driver created to understand WFP Callouts.</p>\n<p>This kernel driver implements the following functions, and in particular it implements important WFP Callout functionality for antivirus products and EDR in a simple form.</p>\n<ol>\n<li>Registering Callout functions with the kernel-mode WFP engine and adding filters at the ALE layer to invoke those Callouts</li>\n<li>Blocking traffic based on decisions made by a resident user-mode program</li>\n<li>Excluding traffic related to specific applications from blocking</li>\n</ol>\n<p>Of the operations in item 1, registering Callout functions must be performed by the kernel driver, but adding filters to invoke the Callout can be done from either kernel mode or user mode.<sup id=\"fnref-1\"><a href=\"#fn-1\" class=\"footnote-ref\">1</a></sup></p>\n<p>Because of that, filters are often registered from the user-mode program side in general, but in this sample program the driver running in kernel mode also implements filter addition.</p>\n<h3 id=\"running-the-sample-program\" style=\"position:relative;\"><a href=\"#running-the-sample-program\" aria-label=\"running the sample program 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>Running the Sample Program</h3>\n<p>Building this sample program generates the following files, so first copy all of them to a virtual machine with test-signing mode enabled.</p>\n<ul>\n<li>KernelWFPCalloutDriver.sys</li>\n<li>KernelWFPCalloutDriver.cer</li>\n<li>UserModeCalloutSample.exe</li>\n</ul>\n<p>Next, register the copied KernelWFPCalloutDriver.sys in the system as KernelWFPCalloutDriver.</p>\n<p>A kernel driver can be installed with the <code class=\"language-text\">sc</code> command and similar tools, but this time I will use OSR Driver Loader to register and start the service 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: 669px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/cb15dea4396f21dc784a8cb590e07dfe/99272/03-wfp-001.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: 129.58333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAABYlAAAWJQFJUiTwAAADZklEQVRIx4WVW08aURDH9xs0fe2XbvukSR/b9J0+1ESbxtBWRVQUdrnfbyogoCAIGqfnNzDblTbpJpM5u+fMf/5zObPe1y8xub7uObmW4c2NXF1dyXw+F57n52exh/Wm8Dw9Pen68fFRFouFeP1+X7qdjgycHjhA3ofDoYzHY7m9vVWN3N3dvRD2BoOBEuh2u9Lr9eTG2XtnZ2fy5vUr+fzpo5RKZTk9PZWTkxPVSDqdlo5zCOhoNFJhjXGj0ZBsNiuJREKq1aq0Wi3xkkdH4nmefNjekmwuJ3t7e7K/v686CAJlbGBRTRSAAHh8fCyFQmEF+OvgQAG33r2TQrEkOzs7sru7K7FYTPL5fBi2sYsCplIpOTw8lCNHKh6PuwhL4jUbddl+/1bDwwMfm82m5BxbvNdqtRAgCorACnbJZFJ1u90Wj8MttyiXyxrCdDrVZHMYhojv+1IsFhV0MpkoawoDqDmyKDyMAYIZrcNB8gazqODQNOBGgIKRa4qHnQLCgvAANa+0A0L4hEJrsKaygLC2PTTOtG1AJV94YYNwrIKwoL/u7+81VDRCWqL9iGafsJUhhrA0L3zLZDIqsIYdBTMnnLNIohLmkJxgiIax5ZV3UgF71vV6PQwTRlGBaQhobAidDUAvLi6EW8Q31gBfXl4qE2xIBeeMAHtoL5ovEk4+2DhwDU/TVioVZWZniMQEZ7SX1UAByRnsYIExiWWDRscIJwbKGo1YU3MOfX5+ruzDtoEBnnAAKD3ZarUdSDO8rzimICVlWtbv8fgPZ5dXp9goQ6MOIzVSNiTfTRmX08Vi6XK7ahNaZjKZyszNzNlspu+z2Vx7UxubygBqAm0GLgcoEBXE6H8P5ymUZ/cwOkh7vf6a4SpkHDCNHx4eQuF99W0hy+VSz4RFIYfcRRoYVngKgqwWCk0FGVXWk5wdRKIy0T6EEYBMaes5cmGNGp3QMHg5xoZr+TN1PAwpCAwYUzDYnH0A0oO+H+jA2LxySMiQw4Rq1wr522Ck7WI/MyvePwGNxea9tCliArNefyCjsUvFuoC0kv0iQkArArmzO02Tk1e6P+PSkM+6QpQ78i2Zk+/JQH6m3TWsNcRfn4d9OBwMnTza1CFs+6NxK6oVN97qXUn47jcblCVVdKlxTV/Exp1ntBngbxBxbaaPR/NKAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/cb15dea4396f21dc784a8cb590e07dfe/8ac56/03-wfp-001.webp 240w,\n/static/cb15dea4396f21dc784a8cb590e07dfe/d3be9/03-wfp-001.webp 480w,\n/static/cb15dea4396f21dc784a8cb590e07dfe/a6306/03-wfp-001.webp 669w\"\n              sizes=\"(max-width: 669px) 100vw, 669px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/cb15dea4396f21dc784a8cb590e07dfe/8ff5a/03-wfp-001.png 240w,\n/static/cb15dea4396f21dc784a8cb590e07dfe/e85cb/03-wfp-001.png 480w,\n/static/cb15dea4396f21dc784a8cb590e07dfe/99272/03-wfp-001.png 669w\"\n            sizes=\"(max-width: 669px) 100vw, 669px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/cb15dea4396f21dc784a8cb590e07dfe/99272/03-wfp-001.png\"\n            alt=\"Registering the kernel driver with OSR Driver Loader\"\n            title=\"Registering the kernel driver with OSR Driver Loader\"\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>After KernelWFPCalloutDriver has been registered and started, run the user-mode program UserModeCalloutSample.exe.</p>\n<p>At that time, you can specify whether to permit or block the traffic filtered by the Callout by using either <code class=\"language-text\">permit</code> or <code class=\"language-text\">block</code> as the command-line argument.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">UserModeCalloutSample<span class=\"token punctuation\">.</span>exe <span class=\"token namespace\">[permit|block]</span></code></pre></div>\n<p>If you actually run this sample program, you can confirm how UserModeCalloutSample.exe instructed the Callout driver to handle traffic.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/515d8ca5bdf0d3be3a790f44ff1e4b94/b5cea/03-wfp-002.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: 46.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABAUlEQVQoz52SyYqFQAxF304URcW1OIHzPCH+/3+lOYF69JNHL3pxqUpMTt1K+dq2TdCyLKp931XXdWn+OA4ZhkGqqpKmaaTve2nbVtI01bosy8S2bXFdV/UywHVd/wXM81yBnud9AoFN06QAA2Q1wLIsP4BJkug3HFqWJY7jqL46ZL3vW+Z51n3XdVLXtQKBEeOMHmLf9yWKItVXICCAZq7jOKozQDhlj2sO4FZA6aHuA4gAUgSQmEbcmSZgiByA8zwlCAIJw1D1BlJsZvjbITnjzsDZI/LUMM+iKHQMCsSVudYT+IQ+r0ytcU/d2yEB0L8cmsfhF2KPEQ6I41hfG/0AAREPTnRKyQUAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/515d8ca5bdf0d3be3a790f44ff1e4b94/8ac56/03-wfp-002.webp 240w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/d3be9/03-wfp-002.webp 480w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/e46b2/03-wfp-002.webp 960w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/c89f9/03-wfp-002.webp 1140w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/515d8ca5bdf0d3be3a790f44ff1e4b94/8ff5a/03-wfp-002.png 240w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/e85cb/03-wfp-002.png 480w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/d9199/03-wfp-002.png 960w,\n/static/515d8ca5bdf0d3be3a790f44ff1e4b94/b5cea/03-wfp-002.png 1140w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/515d8ca5bdf0d3be3a790f44ff1e4b94/d9199/03-wfp-002.png\"\n            alt=\"Checking the traffic handling result with UserModeCalloutSample.exe\"\n            title=\"Checking the traffic handling result with UserModeCalloutSample.exe\"\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>Also, within this sample program, some processes required for name resolution and similar tasks, as well as traffic from the Brave browser, are defined as permitted.\nFor that reason, when UserModeCalloutSample.exe is run with <code class=\"language-text\">block</code>, communication by applications subject to blocking, such as Microsoft Edge, is blocked, while communication by permitted applications such as Brave succeeds.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/2cf6c4347553a1f26837645f18e9f577/22c86/03-wfp-003.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: 88.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAABYlAAAWJQFJUiTwAAADAElEQVQ4y32US2/TQBDHF/ggfFEOiKegCIkTcOLAUy1FKiAEVQsXLvRJQ9MmtuM0rRvba+/6/Upo/8zaSagqtVF+mvHszOzu7Owye6ghjmOkaUakiKIYRVHA9wMcHTmEjcPDIWHDshwcTmwNDiyS1hGNDyzyscDyKkOWp8gLSpgl4B6HdXyM/sEAB4MBPD9EGKU0gY+hbWNodmG1WkiEhyAOadyDr/RQkl8ANs4BjPD/9xc4rYCTsrEL6wjC8SDdEUZZMw41djrhhP5VE1MkANtLXmE/fgstm4eWKhZgFES5gF71AWvOU/wRz9ASL7EXvYNeLEIv30PL58mvYS+k+OINftuvwZ7HV3B7m+Fei+HWBsONnwyPDIbHJsOcznBn5xoealfxoMNwk8bvtoldgvznNIb77cb+hDO8cK+DaeIHFN1gBbr8DoP0nlxFn+iJVRj+CgxvmeQ3+v6Knv8FBv8M0/sEk3+E6S6h7y2hxxdhiWWwyANinwgaEiITQD6hIEpJTPTCP0Hpj4kKlV+g8jJUPEHlxhj5CZhjx+BOAs9Na1yXTprwOJ0sz+C7GQTZJdkkBUkekpSQjiDodB2XsBHaFiLugHU7GkyzTz11jOHQQRBEEELW7Oy0sLa2jq2tbWxubmNrc6uBvhXbEzbXN/CL/NbX18BUf0kpKZGERz0YBAGqqsJ4PK4bPgwDanbqxTCcyKD245zDcV2YugaXVri/t49eRwfLsuaGKJobk9Q3Jc/zWpZlSbKh0ZsxhYpNkqTWkzgi4ibh1EE5S9qyL4NZwGWcTZxPJmJnHcqygNY/xs6+OVvNVE5R34qLJmRnZ1PbVvVU9VJbUfVs6hvUNoUQokaV52zSqT5LqGZXge12m07dpJfjEJqmYXd3F51OB7quwzAMsnXR7XapvXgdc2nCiFbg0IuiTtF1HVqJj0AKemm8+rVRqO2ORqNZslkNzyecGhxPYDB0YVHTekFMJIjTbFbD84dy4QqnBiFDcHpcRUg9GFNNI0qYpBee8nn9H649LXrTUCZiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/2cf6c4347553a1f26837645f18e9f577/8ac56/03-wfp-003.webp 240w,\n/static/2cf6c4347553a1f26837645f18e9f577/d3be9/03-wfp-003.webp 480w,\n/static/2cf6c4347553a1f26837645f18e9f577/e46b2/03-wfp-003.webp 960w,\n/static/2cf6c4347553a1f26837645f18e9f577/7e370/03-wfp-003.webp 1143w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/2cf6c4347553a1f26837645f18e9f577/8ff5a/03-wfp-003.png 240w,\n/static/2cf6c4347553a1f26837645f18e9f577/e85cb/03-wfp-003.png 480w,\n/static/2cf6c4347553a1f26837645f18e9f577/d9199/03-wfp-003.png 960w,\n/static/2cf6c4347553a1f26837645f18e9f577/22c86/03-wfp-003.png 1143w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/2cf6c4347553a1f26837645f18e9f577/d9199/03-wfp-003.png\"\n            alt=\"Traffic from non-permitted applications is blocked\"\n            title=\"Traffic from non-permitted applications is blocked\"\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=\"about-the-sample-program-implementation\" style=\"position:relative;\"><a href=\"#about-the-sample-program-implementation\" aria-label=\"about the sample program implementation 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>About the Sample Program Implementation</h2>\n<h3 id=\"registering-the-driver\" style=\"position:relative;\"><a href=\"#registering-the-driver\" aria-label=\"registering 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>Registering the Driver</h3>\n<p>First, this kernel driver is implemented as a WDM driver, and the <code class=\"language-text\">DriverEntry</code> function that performs initialization mainly carries out the following operations.</p>\n<ul>\n<li>Initializing objects used in the driver, such as the device name (<code class=\"language-text\">SampleWfpCallout</code>), a spin lock, a semaphore, and lists</li>\n<li>Initializing several required IRP handlers</li>\n<li>Initializing the device object and registering the symbolic link</li>\n<li>Registering WFP Callout filters</li>\n</ul>\n<p>In this sample program, the traffic-blocking decision made by the Callout is delegated to a resident user-mode program.</p>\n<p>For that reason, inside <code class=\"language-text\">DriverEntry</code>, <code class=\"language-text\">DispatchDeviceControl</code> is registered as the IRP handler corresponding to <code class=\"language-text\">IRP_MJ_DEVICE_CONTROL</code>, so that information can be exchanged between the user-mode program and the kernel driver.</p>\n<p>In addition, the <code class=\"language-text\">RegisterCalloutAndFilter</code> function called from there registers the Callout functions and WFP filters.</p>\n<p>Most of the processing performed in <code class=\"language-text\">RegisterCalloutAndFilter</code> is almost the same as the filter-registration operation in the sample program used in Chapter 2: it opens a session to the engine, starts a transaction, registers the WFP sublayer and filters, and then commits the transaction.</p>\n<p>However, because this driver registers Callout filters, unlike the sample program used in Chapter 2 it also registers Callouts by using <code class=\"language-text\">FwpsCalloutRegister3</code> and <code class=\"language-text\">FwpmCalloutAdd</code>.</p>\n<p>The details of those operations are explained in the next section.</p>\n<h3 id=\"registering-callout-functions\" style=\"position:relative;\"><a href=\"#registering-callout-functions\" aria-label=\"registering callout 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>Registering Callout Functions</h3>\n<p>In the <code class=\"language-text\">RegisterCalloutAndFilter</code> function implemented on the sample-driver side, the Callout function is first registered by using <code class=\"language-text\">FwpsCalloutRegister3</code>.<sup id=\"fnref-2\"><a href=\"#fn-2\" class=\"footnote-ref\">2</a></sup></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">FWPS_CALLOUT3 callout <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\ncallout<span class=\"token punctuation\">.</span>calloutKey <span class=\"token operator\">=</span> CALLOUT_KEY<span class=\"token punctuation\">;</span>\ncallout<span class=\"token punctuation\">.</span>classifyFn <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>FWPS_CALLOUT_CLASSIFY_FN3<span class=\"token punctuation\">)</span>SampleClassify<span class=\"token punctuation\">;</span>\ncallout<span class=\"token punctuation\">.</span>notifyFn <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>FWPS_CALLOUT_NOTIFY_FN3<span class=\"token punctuation\">)</span>SampleNotify<span class=\"token punctuation\">;</span>\ncallout<span class=\"token punctuation\">.</span>flowDeleteFn <span class=\"token operator\">=</span> SampleFlowDelete<span class=\"token punctuation\">;</span>\n\nstatus <span class=\"token operator\">=</span> <span class=\"token function\">FwpsCalloutRegister3</span><span class=\"token punctuation\">(</span>\n            deviceObject<span class=\"token punctuation\">,</span> \n            <span class=\"token operator\">&amp;</span>callout<span class=\"token punctuation\">,</span> \n            <span class=\"token operator\">&amp;</span>gCalloutId\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The <code class=\"language-text\">FwpsCalloutRegister3</code> function registers the function pointers in the <code class=\"language-text\">FWPS_CALLOUT3</code> structure as Callout functions.<sup id=\"fnref-3\"><a href=\"#fn-3\" class=\"footnote-ref\">3</a></sup></p>\n<p>The <code class=\"language-text\">FWPS_CALLOUT3</code> structure defines the information required for a Callout driver to register function pointers.</p>\n<p>That structure is defined as follows.</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\">FWPS_CALLOUT3_</span> <span class=\"token punctuation\">{</span>\n  GUID                                calloutKey<span class=\"token punctuation\">;</span>\n  UINT32                              flags<span class=\"token punctuation\">;</span>\n  FWPS_CALLOUT_CLASSIFY_FN3           classifyFn<span class=\"token punctuation\">;</span>\n  FWPS_CALLOUT_NOTIFY_FN3             notifyFn<span class=\"token punctuation\">;</span>\n  FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 flowDeleteFn<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> FWPS_CALLOUT3<span class=\"token punctuation\">;</span></code></pre></div>\n<p>Among these parameters, <code class=\"language-text\">classifyFn</code> and <code class=\"language-text\">notifyFn</code> correspond to pointers to the functions to register, and are passed as pointers to the <code class=\"language-text\">FWPS_CALLOUT_CLASSIFY_FN3</code> callback type<sup id=\"fnref-4\"><a href=\"#fn-4\" class=\"footnote-ref\">4</a></sup> and the <code class=\"language-text\">FWPS_CALLOUT_NOTIFY_FN3</code> callback type<sup id=\"fnref-5\"><a href=\"#fn-5\" class=\"footnote-ref\">5</a></sup>, respectively.</p>\n<p>In this code, <code class=\"language-text\">SampleClassify</code>, a function defined in this driver’s code, is set in <code class=\"language-text\">classifyFn</code>, and <code class=\"language-text\">SampleNotify</code> is set in <code class=\"language-text\">notifyFn</code>.</p>\n<p>The <code class=\"language-text\">FWPS_CALLOUT3</code> structure, which defines information about the function pointers registered by <code class=\"language-text\">FwpsCalloutRegister3</code>, includes two kinds of function pointers: <code class=\"language-text\">classifyFn</code> (<code class=\"language-text\">FWPS_CALLOUT_CLASSIFY_FN3</code>), which is a Callout function invoked when there is network data to be processed by the Callout, and <code class=\"language-text\">notifyFn</code> (<code class=\"language-text\">FWPS_CALLOUT_NOTIFY_FN3</code>), which is invoked to notify events related to the Callout.</p>\n<h3 id=\"the-classification-callout-function-registered-in-classifyfn\" style=\"position:relative;\"><a href=\"#the-classification-callout-function-registered-in-classifyfn\" aria-label=\"the classification callout function registered in classifyfn 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>The Classification Callout Function Registered in classifyFn</h3>\n<p>In this sample program, <code class=\"language-text\">SampleClassify</code> is implemented as the Callout function for classification processing.</p>\n<p>A classification Callout function is the function that processes network data through the Callout, and it is called by the filter engine together with several pieces of data.<sup id=\"fnref-6\"><a href=\"#fn-6\" class=\"footnote-ref\">6</a></sup></p>\n<p>When this classification Callout function is invoked, information such as the <code class=\"language-text\">FWPS_INCOMING_VALUES0</code> structure and the <code class=\"language-text\">FWPS_INCOMING_METADATA_VALUES0</code> structure is provided as parameters.</p>\n<p>First, the <code class=\"language-text\">FWPS_INCOMING_VALUES0</code> structure<sup id=\"fnref-7\"><a href=\"#fn-7\" class=\"footnote-ref\">7</a></sup> passed to the classification Callout function is defined as follows, in a form that contains the <code class=\"language-text\">FWPS_INCOMING_VALUE0</code> structure<sup id=\"fnref-8\"><a href=\"#fn-8\" class=\"footnote-ref\">8</a></sup>, which holds the actual data.</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\">FWPS_INCOMING_VALUE0_</span> <span class=\"token punctuation\">{</span>\n  FWP_VALUE0 value<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> FWPS_INCOMING_VALUE0<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">typedef</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">FWPS_INCOMING_VALUES0_</span> <span class=\"token punctuation\">{</span>\n  UINT16               layerId<span class=\"token punctuation\">;</span>\n  UINT32               valueCount<span class=\"token punctuation\">;</span>\n  FWPS_INCOMING_VALUE0 <span class=\"token operator\">*</span>incomingValue<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> FWPS_INCOMING_VALUES0<span class=\"token punctuation\">;</span></code></pre></div>\n<p>The <code class=\"language-text\">incomingValue</code> field of <code class=\"language-text\">FWPS_INCOMING_VALUES0</code> is a pointer to an array of <code class=\"language-text\">FWPS_INCOMING_VALUE0</code> structures that contain the actual data (<code class=\"language-text\">FWP_VALUE0</code>), and <code class=\"language-text\">valueCount</code> is the number of elements in the array passed as <code class=\"language-text\">incomingValue</code>.</p>\n<p>Likewise, the <code class=\"language-text\">FWPS_INCOMING_METADATA_VALUES0</code> structure passed as a parameter to the classification Callout function contains various kinds of metadata given to the Callout function by the filter engine.</p>\n<p>In this sample program, a filter is registered on the <code class=\"language-text\">FWPM_LAYER_ALE_AUTH_CONNECT_V4</code> layer, and the runtime filtering layer<sup id=\"fnref-9\"><a href=\"#fn-9\" class=\"footnote-ref\">9</a></sup> used by the Callout function is <code class=\"language-text\">FWPS_LAYER_ALE_AUTH_CONNECT_V4</code>.<sup id=\"fnref-10\"><a href=\"#fn-10\" class=\"footnote-ref\">10</a></sup></p>\n<p>Therefore, the data in the <code class=\"language-text\">FWPS_INCOMING_VALUES0</code> structure (<code class=\"language-text\">incomingValue</code>) passed as a parameter to the classification Callout function can be accessed by using values from the <code class=\"language-text\">FWPS_FIELDS_ALE_AUTH_CONNECT_V4</code> enumeration<sup id=\"fnref-11\"><a href=\"#fn-11\" class=\"footnote-ref\">11</a></sup> as data-field identifiers, as shown below.<sup id=\"fnref-12\"><a href=\"#fn-12\" class=\"footnote-ref\">12</a></sup></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">remoteAddressV4 <span class=\"token operator\">=</span> inFixedValues<span class=\"token operator\">-></span>incomingValue<span class=\"token punctuation\">[</span>FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>uint32<span class=\"token punctuation\">;</span>\n\nremotePort <span class=\"token operator\">=</span> inFixedValues<span class=\"token operator\">-></span>incomingValue<span class=\"token punctuation\">[</span>FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>uint16<span class=\"token punctuation\">;</span>\n\nlocalPort <span class=\"token operator\">=</span> inFixedValues<span class=\"token operator\">-></span>incomingValue<span class=\"token punctuation\">[</span>FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>uint16<span class=\"token punctuation\">;</span>\n\nipProtocol <span class=\"token operator\">=</span> inFixedValues<span class=\"token operator\">-></span>incomingValue<span class=\"token punctuation\">[</span>FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>uint8<span class=\"token punctuation\">;</span>\n\naleFlags <span class=\"token operator\">=</span> inFixedValues<span class=\"token operator\">-></span>incomingValue<span class=\"token punctuation\">[</span>FWPS_FIELD_ALE_AUTH_CONNECT_V4_FLAGS<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>uint32<span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the <code class=\"language-text\">SampleClassify</code> function called for classification processing, several pieces of metadata included in the <code class=\"language-text\">FWPS_INCOMING_METADATA_VALUES0</code> structure (<code class=\"language-text\">inMetaValues</code>) received as a parameter are also evaluated.</p>\n<p>For example, the code below refers to the metadata-field identifiers (<code class=\"language-text\">currentMetadataValues</code>), which indicate the metadata values set in the structure, checks whether process ID information can be obtained from the presence or absence of the <code class=\"language-text\">FWPS_METADATA_FIELD_PROCESS_ID</code> bit, and, when it can be obtained, stores that process ID information in <code class=\"language-text\">processId</code>.<sup id=\"fnref-13\"><a href=\"#fn-13\" class=\"footnote-ref\">13</a></sup></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>inMetaValues<span class=\"token operator\">-></span>currentMetadataValues <span class=\"token operator\">&amp;</span> FWPS_METADATA_FIELD_PROCESS_ID<span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    processId <span class=\"token operator\">=</span> inMetaValues<span class=\"token operator\">-></span>processId<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>After that, in the classification Callout function <code class=\"language-text\">SampleClassify</code>, the driver evaluates whether the network traffic notified to the Callout function is traffic for which “ALE flow reauthorization” has been requested, and if it is not a reauthorization request, it suspends traffic processing by using <code class=\"language-text\">FwpsPendOperation0</code>.</p>\n<p>On the other hand, if the notified network traffic is a reauthorization request, the traffic is blocked or permitted based on the decision result from the user-mode program.</p>\n<p>This coordination between the Callout function and the user-mode program is explained later.</p>\n<h3 id=\"the-event-notification-callout-function-registered-in-notifyfn\" style=\"position:relative;\"><a href=\"#the-event-notification-callout-function-registered-in-notifyfn\" aria-label=\"the event notification callout function registered in notifyfn 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>The Event Notification Callout Function Registered in notifyFn</h3>\n<p>In this sample program, <code class=\"language-text\">SampleNotify</code> is implemented as the event-notification Callout function.</p>\n<p>Unlike the classification Callout function explained in the previous section, the event-notification Callout function is called when events such as filter addition or deletion occur.<sup id=\"fnref-14\"><a href=\"#fn-14\" class=\"footnote-ref\">14</a></sup></p>\n<p>In this sample program, the event-notification Callout <code class=\"language-text\">SampleNotify</code> is implemented very simply as follows: it receives, as a parameter, a value of the <code class=\"language-text\">FWPS_CALLOUT_NOTIFY_TYPE</code> enumeration (<code class=\"language-text\">notifyType</code>) that contains information about the kind of event that occurred, and outputs the occurrence of the event as a debug message based on that result.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>notifyType<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">case</span> FWPS_CALLOUT_NOTIFY_ADD_FILTER<span class=\"token operator\">:</span>\n        <span class=\"token function\">DbgPrintEx</span><span class=\"token punctuation\">(</span>\n            DPFLTR_IHVDRIVER_ID<span class=\"token punctuation\">,</span> \n            DPFLTR_INFO_LEVEL<span class=\"token punctuation\">,</span> \n            <span class=\"token string\">\"Sample callout: filter added\\n\"</span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">case</span> FWPS_CALLOUT_NOTIFY_DELETE_FILTER<span class=\"token operator\">:</span>\n        <span class=\"token function\">DbgPrintEx</span><span class=\"token punctuation\">(</span>\n            DPFLTR_IHVDRIVER_ID<span class=\"token punctuation\">,</span> \n            DPFLTR_INFO_LEVEL<span class=\"token punctuation\">,</span> \n            <span class=\"token string\">\"Sample callout: filter deleted\\n\"</span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">return</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"controlling-traffic-by-coordinating-the-callout-driver-with-a-user-mode-program\" style=\"position:relative;\"><a href=\"#controlling-traffic-by-coordinating-the-callout-driver-with-a-user-mode-program\" aria-label=\"controlling traffic by coordinating the callout driver with a user mode program 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>Controlling Traffic by Coordinating the Callout Driver with a User-Mode Program</h2>\n<p>In the sample program explained in this chapter, the decision result from the user-mode program is used to block traffic through the Callout driver.</p>\n<p>In this section, I will explain in detail the coordination between the Callout driver and the user-mode program, which is the core function of this sample program.</p>\n<h3 id=\"coordination-between-the-callout-driver-and-the-user-mode-program\" style=\"position:relative;\"><a href=\"#coordination-between-the-callout-driver-and-the-user-mode-program\" aria-label=\"coordination between the callout driver and the user mode program 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>Coordination Between the Callout Driver and the User-Mode Program</h3>\n<p>A WFP Callout driver can use the classification Callout function registered in <code class=\"language-text\">classifyFn</code> to transfer the information contained in each parameter received by the Callout function to a user-mode program, and can block or permit network traffic based on the decision result from that user-mode program.</p>\n<p>Such operations are often performed asynchronously, but the way they are implemented differs depending on the layer that is used.</p>\n<p>In this sample program, processing is performed at the ALE Connect layer, so the operation is first suspended by calling <code class=\"language-text\">FwpsPendOperation0</code> from the function registered as <code class=\"language-text\">classifyFn</code>, and then, when processing on the user-mode-program side becomes possible, <code class=\"language-text\">FwpsCompleteOperation0</code> is called to complete the classification processing.<sup id=\"fnref-15\"><a href=\"#fn-15\" class=\"footnote-ref\">15</a></sup></p>\n<p>The <code class=\"language-text\">FwpsPendOperation0</code> function<sup id=\"fnref-16\"><a href=\"#fn-16\" class=\"footnote-ref\">16</a></sup> is called by a Callout function to temporarily suspend classification processing that needs to wait for the completion of another operation by a user-mode program or similar component.</p>\n<p>This function is defined as follows, and it is called by passing the <code class=\"language-text\">completionHandle</code> included in the <code class=\"language-text\">FWPS_INCOMING_METADATA_VALUES0</code> structure, which is provided as a parameter when the classification Callout function is invoked, and by storing the handle corresponding to the suspended operation as <code class=\"language-text\">completionContext</code>.</p>\n<p>The handle kept in <code class=\"language-text\">completionContext</code> is used when <code class=\"language-text\">FwpsCompleteOperation0</code> is called.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">NTSTATUS <span class=\"token function\">FwpsPendOperation0</span><span class=\"token punctuation\">(</span>\n  <span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>  HANDLE completionHandle<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span>out<span class=\"token punctuation\">]</span> HANDLE <span class=\"token operator\">*</span>completionContext\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The <code class=\"language-text\">FwpsCompleteOperation0</code> function<sup id=\"fnref-17\"><a href=\"#fn-17\" class=\"footnote-ref\">17</a></sup> is called to resume a suspended operation, and it receives the <code class=\"language-text\">completionContext</code> that was saved when classification processing was suspended as a parameter.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">void</span> <span class=\"token function\">FwpsCompleteOperation0</span><span class=\"token punctuation\">(</span>\n<span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">]</span>           HANDLE           completionContext<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">[</span>in<span class=\"token punctuation\">,</span> optional<span class=\"token punctuation\">]</span> PNET_BUFFER_LIST netBufferList\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"suspending-classification-in-the-sample-program\" style=\"position:relative;\"><a href=\"#suspending-classification-in-the-sample-program\" aria-label=\"suspending classification in the sample program 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>Suspending Classification in the Sample Program</h3>\n<p>On the kernel-driver side of this sample program, classification is suspended inside the <code class=\"language-text\">SampleClassify</code> function, which is registered as the classification Callout function, as follows.</p>\n<ol>\n<li>Refer to the filtering condition flags<sup id=\"fnref-18\"><a href=\"#fn-18\" class=\"footnote-ref\">18</a></sup> included in the <code class=\"language-text\">FWPS_INCOMING_VALUES0</code> structure (<code class=\"language-text\">inFixedValues</code>) and check whether the <code class=\"language-text\">FWP_CONDITION_FLAG_IS_REAUTHORIZE</code> flag is present (that is, determine whether this is a new connection)</li>\n<li>If the target is a new connection, call <code class=\"language-text\">FwpsPendOperation0</code> to suspend processing</li>\n<li>Temporarily save information about the connection request in <code class=\"language-text\">pending</code>, a memory region allocated from the nonpaged pool, for coordination with the user-mode program</li>\n</ol>\n<p>Specifically, the call to <code class=\"language-text\">FwpsPendOperation0</code> and the saving of information into <code class=\"language-text\">pending</code> are implemented with the following code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">status <span class=\"token operator\">=</span> <span class=\"token function\">FwpsPendOperation0</span><span class=\"token punctuation\">(</span>\n            <span class=\"token punctuation\">(</span>HANDLE<span class=\"token punctuation\">)</span>inMetaValues<span class=\"token operator\">-></span>completionHandle<span class=\"token punctuation\">,</span>\n            <span class=\"token operator\">&amp;</span>completionContext\n         <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* 省略 */</span>\n\nPENDING_CLASSIFY<span class=\"token operator\">*</span> pending <span class=\"token operator\">=</span> \\\n    <span class=\"token punctuation\">(</span>PENDING_CLASSIFY<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">ExAllocatePool2</span><span class=\"token punctuation\">(</span>\n        POOL_FLAG_NON_PAGED<span class=\"token punctuation\">,</span> \n        <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>PENDING_CLASSIFY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n        <span class=\"token char\">'pfCW'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* 省略 */</span>\n\n<span class=\"token function\">RtlZeroMemory</span><span class=\"token punctuation\">(</span>pending<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pending<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>RequestId <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>UINT64<span class=\"token punctuation\">)</span><span class=\"token function\">InterlockedIncrement64</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gNextRequestId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>CompletionContext <span class=\"token operator\">=</span> completionContext<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>ProcessId <span class=\"token operator\">=</span> processId<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>RemoteAddressV4 <span class=\"token operator\">=</span> remoteAddressV4<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>RemotePort <span class=\"token operator\">=</span> remotePort<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>LocalPort <span class=\"token operator\">=</span> localPort<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>IpProtocol <span class=\"token operator\">=</span> ipProtocol<span class=\"token punctuation\">;</span>\npending<span class=\"token operator\">-></span>Queued <span class=\"token operator\">=</span> TRUE<span class=\"token punctuation\">;</span></code></pre></div>\n<p>After acquiring a spin lock for safe operation, the information saved by the code above is added to the relevant lists by using <code class=\"language-text\">InsertTailList</code>.</p>\n<p>The semaphore count is also incremented by <code class=\"language-text\">KeReleaseSemaphore</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">KIRQL oldIrql<span class=\"token punctuation\">;</span>\n<span class=\"token function\">KeAcquireSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">InsertTailList</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gOutstandingList<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>pending<span class=\"token operator\">-></span>OutstandingEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">InsertTailList</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingQueue<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>pending<span class=\"token operator\">-></span>QueueEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">KeReleaseSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">KeReleaseSemaphore</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingSemaphore<span class=\"token punctuation\">,</span> IO_NO_INCREMENT<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> FALSE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>This information is used when coordinating with the user-mode program.</p>\n<p>After <code class=\"language-text\">SampleClassify</code> performs the suspension processing above for a first-time connection, it finally returns <code class=\"language-text\">FWP_ACTION_BLOCK</code> with the <code class=\"language-text\">FWPS_CLASSIFY_OUT_FLAG_ABSORB</code> flag, which silently discards blocked data without recording it in the event log or auditing it.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">classifyOut<span class=\"token operator\">-></span>actionType <span class=\"token operator\">=</span> FWP_ACTION_BLOCK<span class=\"token punctuation\">;</span>\nclassifyOut<span class=\"token operator\">-></span>flags <span class=\"token operator\">|=</span> FWPS_CLASSIFY_OUT_FLAG_ABSORB<span class=\"token punctuation\">;</span>\nclassifyOut<span class=\"token operator\">-></span>rights <span class=\"token operator\">&amp;=</span> <span class=\"token operator\">~</span>FWPS_RIGHT_ACTION_WRITE<span class=\"token punctuation\">;</span></code></pre></div>\n<p>This completes the suspension of the connection by the Callout function.</p>\n<h3 id=\"processing-ioctls\" style=\"position:relative;\"><a href=\"#processing-ioctls\" aria-label=\"processing ioctls 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>Processing IOCTLs</h3>\n<p>In this sample program, coordination with the user-mode program is performed by using <code class=\"language-text\">IRP_MJ_DEVICE_CONTROL</code> and the corresponding IRP handler function <code class=\"language-text\">DispatchDeviceControl</code>.</p>\n<p>Here, one of the following custom-defined IOCTLs sent from the user-mode program by <code class=\"language-text\">DeviceIoControl</code> is handled.</p>\n<ul>\n<li><code class=\"language-text\">IOCTL_WFP_GET_NEXT_REQUEST</code></li>\n<li><code class=\"language-text\">IOCTL_WFP_SUBMIT_DECISION</code></li>\n</ul>\n<p><code class=\"language-text\">IOCTL_WFP_GET_NEXT_REQUEST</code> is used by the user-mode program to obtain, from the kernel-driver side, information about connection requests that were suspended by the Callout function.</p>\n<p>On the other hand, <code class=\"language-text\">IOCTL_WFP_SUBMIT_DECISION</code> is used by the user-mode program to notify the decision result for a request obtained from the kernel-driver side.</p>\n<p>Requests for <code class=\"language-text\">IOCTL_WFP_GET_NEXT_REQUEST</code> are issued from the user-mode-program side with the following code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">BOOL ok <span class=\"token operator\">=</span> <span class=\"token function\">DeviceIoControl</span><span class=\"token punctuation\">(</span>\n    device<span class=\"token punctuation\">,</span>\n    IOCTL_WFP_GET_NEXT_REQUEST<span class=\"token punctuation\">,</span>\n    nullptr<span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n    <span class=\"token operator\">&amp;</span>request<span class=\"token punctuation\">,</span>\n    <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>request<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token operator\">&amp;</span>bytesReturned<span class=\"token punctuation\">,</span>\n    nullptr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The <code class=\"language-text\">request</code> passed as a parameter is an object of the <code class=\"language-text\">USER_CLASSIFY_REQUEST</code> structure, and it is used to receive information about traffic to be classified from the kernel-driver side.</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\">_USER_CLASSIFY_REQUEST</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token keyword\">long</span> RequestId<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token keyword\">long</span> ProcessId<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> RemoteAddressV4<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">short</span> RemotePort<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">short</span> Reserved<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> USER_CLASSIFY_REQUEST<span class=\"token punctuation\">;</span></code></pre></div>\n<p>On the kernel-driver side, when an IOCTL request for <code class=\"language-text\">IOCTL_WFP_GET_NEXT_REQUEST</code> is received, the following operations are mainly performed.</p>\n<ul>\n<li>Confirm that the driver is not stopping, and use the <code class=\"language-text\">KeWaitForSingleObject</code> function<sup id=\"fnref-20\"><a href=\"#fn-20\" class=\"footnote-ref\">20</a></sup> to ensure that <code class=\"language-text\">gPendingSemaphore</code> is in the signaled state and that at least one pending event exists</li>\n<li>If a pending event exists, take one event from <code class=\"language-text\">gPendingQueue</code>, which is used as the queue, and store its information as a <code class=\"language-text\">PENDING_CLASSIFY</code> structure</li>\n<li>Finally, store the <code class=\"language-text\">USER_CLASSIFY_REQUEST</code> structure and the corresponding information in the output buffer specified by the user-mode program when calling <code class=\"language-text\">DeviceIoControl</code></li>\n</ul>\n<p>Of the operations above, the processing that passes information obtained from the queue to the user-mode program is implemented mainly by the following code.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">KIRQL oldIrql<span class=\"token punctuation\">;</span>\nPENDING_CLASSIFY<span class=\"token operator\">*</span> pending <span class=\"token operator\">=</span> nullptr<span class=\"token punctuation\">;</span>\nUSER_CLASSIFY_REQUEST<span class=\"token operator\">*</span> request <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>USER_CLASSIFY_REQUEST<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>irp<span class=\"token operator\">-></span>AssociatedIrp<span class=\"token punctuation\">.</span>SystemBuffer<span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">KeAcquireSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>oldIrql<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\">IsListEmpty</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingQueue<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    PLIST_ENTRY queueEntry <span class=\"token operator\">=</span> <span class=\"token function\">RemoveHeadList</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingQueue<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    pending <span class=\"token operator\">=</span> <span class=\"token function\">CONTAINING_RECORD</span><span class=\"token punctuation\">(</span>queueEntry<span class=\"token punctuation\">,</span> PENDING_CLASSIFY<span class=\"token punctuation\">,</span> QueueEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    pending<span class=\"token operator\">-></span>Queued <span class=\"token operator\">=</span> FALSE<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token function\">KeReleaseSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>pending <span class=\"token operator\">==</span> nullptr<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    status <span class=\"token operator\">=</span> STATUS_RETRY<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">else</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token function\">DbgPrintEx</span><span class=\"token punctuation\">(</span>DPFLTR_IHVDRIVER_ID<span class=\"token punctuation\">,</span> DPFLTR_INFO_LEVEL<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"Sample callout: dispatch request id=%llu pid=%llu\\n\"</span><span class=\"token punctuation\">,</span>\n        pending<span class=\"token operator\">-></span>RequestId<span class=\"token punctuation\">,</span>\n        pending<span class=\"token operator\">-></span>ProcessId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    request<span class=\"token operator\">-></span>RequestId <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>RequestId<span class=\"token punctuation\">;</span>\n    request<span class=\"token operator\">-></span>ProcessId <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>ProcessId<span class=\"token punctuation\">;</span>\n    request<span class=\"token operator\">-></span>RemoteAddressV4 <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>RemoteAddressV4<span class=\"token punctuation\">;</span>\n    request<span class=\"token operator\">-></span>RemotePort <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>RemotePort<span class=\"token punctuation\">;</span>\n    request<span class=\"token operator\">-></span>Reserved <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n    information <span class=\"token operator\">=</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>USER_CLASSIFY_REQUEST<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    status <span class=\"token operator\">=</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>On the other hand, when an IOCTL request corresponding to <code class=\"language-text\">IOCTL_WFP_SUBMIT_DECISION</code> is received, the kernel-driver side mainly performs the following operations.</p>\n<ul>\n<li>Save the decision result for the traffic sent from the user-mode program</li>\n<li>Retrieve, from the list, information about the traffic whose <code class=\"language-text\">RequestId</code> matches the <code class=\"language-text\">RequestId</code> contained in the information received from the user-mode program</li>\n<li>Allocate, in the nonpaged pool, an entry that contains the traffic information and its decision result, and add it to the list that is consulted when an ALE flow reauthorization request causes the <code class=\"language-text\">FWP_CONDITION_FLAG_IS_REAUTHORIZE</code> flag to be set</li>\n<li>Pass parameters related to the pending target traffic to <code class=\"language-text\">FwpsCompleteOperation0</code> and execute it</li>\n</ul>\n<p>These operations are implemented mainly as follows.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">DECISION_ENTRY<span class=\"token operator\">*</span> decisionEntry <span class=\"token operator\">=</span> \\\n    <span class=\"token punctuation\">(</span>DECISION_ENTRY<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">ExAllocatePool2</span><span class=\"token punctuation\">(</span>\n        POOL_FLAG_NON_PAGED<span class=\"token punctuation\">,</span> \n        <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>DECISION_ENTRY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token char\">'dfCW'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* 省略 */</span>\n\n<span class=\"token function\">RtlZeroMemory</span><span class=\"token punctuation\">(</span>decisionEntry<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>decisionEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>ProcessId <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>ProcessId<span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>RemoteAddressV4 <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>RemoteAddressV4<span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>RemotePort <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>RemotePort<span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>LocalPort <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>LocalPort<span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>IpProtocol <span class=\"token operator\">=</span> pending<span class=\"token operator\">-></span>IpProtocol<span class=\"token punctuation\">;</span>\ndecisionEntry<span class=\"token operator\">-></span>Block <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>decision<span class=\"token operator\">-></span>Block <span class=\"token operator\">!=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> TRUE <span class=\"token operator\">:</span> FALSE<span class=\"token punctuation\">;</span>\n\n\n<span class=\"token function\">KeAcquireSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">InsertTailList</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gDecisionList<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>decisionEntry<span class=\"token operator\">-></span>ListEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">KeReleaseSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">DbgPrintEx</span><span class=\"token punctuation\">(</span>DPFLTR_IHVDRIVER_ID<span class=\"token punctuation\">,</span> DPFLTR_INFO_LEVEL<span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"Sample callout: submit decision id=%llu block=%lu\\n\"</span><span class=\"token punctuation\">,</span>\n    decision<span class=\"token operator\">-></span>RequestId<span class=\"token punctuation\">,</span>\n    decision<span class=\"token operator\">-></span>Block<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">CompleteAndFreePending</span><span class=\"token punctuation\">(</span>pending<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nstatus <span class=\"token operator\">=</span> STATUS_SUCCESS<span class=\"token punctuation\">;</span>\ninformation <span class=\"token operator\">=</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>USER_CLASSIFY_DECISION<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>At this point, information exchange with the user-mode program has taken place, and the information including the final decision result has been added to <code class=\"language-text\">gDecisionList</code>, the list consulted when an ALE flow reauthorization request causes the <code class=\"language-text\">FWP_CONDITION_FLAG_IS_REAUTHORIZE</code> flag to be set.</p>\n<p>Finally, that decision result is used so that the Callout function can block or permit traffic.</p>\n<h3 id=\"performing-traffic-classification\" style=\"position:relative;\"><a href=\"#performing-traffic-classification\" aria-label=\"performing traffic classification 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>Performing Traffic Classification</h3>\n<p>As described above, inside <code class=\"language-text\">SampleClassify</code>, which is registered as the classification Callout function, the first connection request was suspended by <code class=\"language-text\">FwpsPendOperation0</code>, and the function waited to receive the decision result from the user-mode program side.</p>\n<p>After that, when the kernel driver receives the IOCTL request corresponding to <code class=\"language-text\">IOCTL_WFP_SUBMIT_DECISION</code> from the user-mode program side, it calls <code class=\"language-text\">FwpsCompleteOperation0</code> for the suspended traffic.</p>\n<p>When <code class=\"language-text\">FwpsCompleteOperation0</code> is called for pending traffic, it triggers an ALE flow reauthorization request.<sup id=\"fnref-21\"><a href=\"#fn-21\" class=\"footnote-ref\">21</a></sup></p>\n<p>After that, the classification Callout function is invoked again for that ALE flow reauthorization request, and this time the following section of code is executed.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>aleFlags <span class=\"token operator\">&amp;</span> FWP_CONDITION_FLAG_IS_REAUTHORIZE<span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    KIRQL oldIrql<span class=\"token punctuation\">;</span>\n    DECISION_ENTRY<span class=\"token operator\">*</span> decision <span class=\"token operator\">=</span> nullptr<span class=\"token punctuation\">;</span>\n    BOOLEAN block <span class=\"token operator\">=</span> TRUE<span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">KeAcquireSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    decision <span class=\"token operator\">=</span> <span class=\"token function\">TakeDecisionLocked</span><span class=\"token punctuation\">(</span>processId<span class=\"token punctuation\">,</span> remoteAddressV4<span class=\"token punctuation\">,</span> remotePort<span class=\"token punctuation\">,</span> localPort<span class=\"token punctuation\">,</span> ipProtocol<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">KeReleaseSpinLock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>gPendingLock<span class=\"token punctuation\">,</span> oldIrql<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>decision <span class=\"token operator\">!=</span> nullptr<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        block <span class=\"token operator\">=</span> decision<span class=\"token operator\">-></span>Block<span class=\"token punctuation\">;</span>\n        <span class=\"token function\">ExFreePoolWithTag</span><span class=\"token punctuation\">(</span>decision<span class=\"token punctuation\">,</span> <span class=\"token char\">'dfCW'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    classifyOut<span class=\"token operator\">-></span>actionType <span class=\"token operator\">=</span> block <span class=\"token operator\">?</span> FWP_ACTION_BLOCK <span class=\"token operator\">:</span> FWP_ACTION_PERMIT<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>block<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        classifyOut<span class=\"token operator\">-></span>rights <span class=\"token operator\">&amp;=</span> <span class=\"token operator\">~</span>FWPS_RIGHT_ACTION_WRITE<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">DbgPrintEx</span><span class=\"token punctuation\">(</span>DPFLTR_IHVDRIVER_ID<span class=\"token punctuation\">,</span> DPFLTR_INFO_LEVEL<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"Sample callout: reauth decision pid=%llu action=%s\\n\"</span><span class=\"token punctuation\">,</span>\n        processId<span class=\"token punctuation\">,</span>\n        block <span class=\"token operator\">?</span> <span class=\"token string\">\"BLOCK\"</span> <span class=\"token operator\">:</span> <span class=\"token string\">\"PERMIT\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this code, the information containing the final decision result received from the user-mode program is retrieved from the list, and based on that result, <code class=\"language-text\">actionType</code> is set to <code class=\"language-text\">FWP_ACTION_BLOCK</code> or <code class=\"language-text\">FWP_ACTION_PERMIT</code>, thereby blocking or permitting traffic through the Callout.</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>In this chapter, I explained a basic implementation for controlling traffic at the ALE layer by using a WFP Callout driver.</p>\n<p>Traffic analysis and similar operations performed in coordination with a user-mode program, as explained in this chapter, form the foundation of how antivirus products and EDR make use of WFP.</p>\n<p>WFP Callouts can implement many operations beyond what was covered in this chapter, including stream inspection and re-injection, but I think the sample program explained in this chapter serves as the minimum foundation for understanding them.</p>\n<h2 id=\"afterword\" style=\"position:relative;\"><a href=\"#afterword\" aria-label=\"afterword 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>Afterword</h2>\n<p>Thank you very much for reading to the end.</p>\n<p>In this book, I have explained things step by step, from the basic architecture of Windows Filtering Platform (WFP), to filter registration in user mode, and then to traffic control with a Callout driver.</p>\n<p>In particular, from the perspective of implementations that become important in antivirus products and EDR, I tried to structure it so that readers could understand, in as practical a form as possible, the questions of which layer to use, what information to use, and how to make decisions.</p>\n<p>At the same time, there are many topics in WFP that this book could not fully cover.</p>\n<p>For example, more complex stream inspection and re-injection behavior are topics that I think are worth exploring further when discussing WFP in the context of antivirus products and EDR.</p>\n<p>I hope this book will serve as a foothold when you begin to understand or implement security features using WFP.</p>\n<h2 id=\"table-of-contents-for-this-book\" style=\"position:relative;\"><a href=\"#table-of-contents-for-this-book\" aria-label=\"table of contents for this book 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 for This Book</h2>\n<ul>\n<li><a href=\"/a-part-of-anti-virus-3-00-en\">Preface</a></li>\n<li><a href=\"/a-part-of-anti-virus-3-01-en\">Chapter 1: Overview and Architecture of WFP</a></li>\n<li><a href=\"/a-part-of-anti-virus-3-02-en\">Chapter 2: Sample for Access Control with WFP</a></li>\n<li><a href=\"/a-part-of-anti-virus-3-03-en\">Chapter 3: Sample for Access Control with a Callout Driver</a></li>\n</ul>\n<div class=\"footnotes\">\n<hr>\n<ol>\n<li id=\"fn-1\">\n<p>Windows Kernel Programming, Second Edition p.493 (by Pavel Yosifovich / Independently published / 2023)</p>\n<a href=\"#fnref-1\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-2\">\n<p>FwpsCalloutRegister3 function (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpscalloutregister3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpscalloutregister3</a></p>\n<a href=\"#fnref-2\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-3\">\n<p><code class=\"language-text\">FWPS_CALLOUT3</code> structure (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/ns-fwpsk-fwps_callout3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/ns-fwpsk-fwps_callout3</a></p>\n<a href=\"#fnref-3\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-4\">\n<p><code class=\"language-text\">FWPS_CALLOUT_CLASSIFY_FN3</code> callback function (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps_callout_classify_fn3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps<em>callout</em>classify_fn3</a></p>\n<a href=\"#fnref-4\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-5\">\n<p><code class=\"language-text\">FWPS_CALLOUT_NOTIFY_FN3</code> callback function (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps_callout_notify_fn3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps<em>callout</em>notify_fn3</a></p>\n<a href=\"#fnref-5\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-6\">\n<p>Processing Classify Callouts <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-classify-callouts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-classify-callouts</a></p>\n<a href=\"#fnref-6\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-7\">\n<p><code class=\"language-text\">FWPS_INCOMING_VALUES0</code> structure (fwpstypes.h) <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/fwpstypes/ns-fwpstypes-fwps_incoming_values0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows/win32/api/fwpstypes/ns-fwpstypes-fwps<em>incoming</em>values0</a></p>\n<a href=\"#fnref-7\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-8\">\n<p><code class=\"language-text\">FWPS_INCOMING_VALUE0</code> structure (fwpstypes.h) <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/fwpstypes/ns-fwpstypes-fwps_incoming_value0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows/win32/api/fwpstypes/ns-fwpstypes-fwps<em>incoming</em>value0</a></p>\n<a href=\"#fnref-8\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-9\">\n<p>Run-time filtering layer identifiers <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/run-time-filtering-layer-identifiers\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/run-time-filtering-layer-identifiers</a></p>\n<a href=\"#fnref-9\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-10\">\n<p>Filtering layer identifiers <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/fwp/management-filtering-layer-identifiers-#remarks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows/win32/fwp/management-filtering-layer-identifiers-#remarks</a></p>\n<a href=\"#fnref-10\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-11\">\n<p><code class=\"language-text\">FWPS_FIELDS_ALE_AUTH_CONNECT_V4</code> enumeration (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/ne-fwpsk-fwps_fields_ale_auth_connect_v4_\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/ne-fwpsk-fwps<em>fields</em>ale<em>auth</em>connect<em>v4</em></a></p>\n<a href=\"#fnref-11\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-12\">\n<p>Data field identifiers <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/data-field-identifiers\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/data-field-identifiers</a></p>\n<a href=\"#fnref-12\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-13\">\n<p>Metadata field identifiers <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/metadata-field-identifiers\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/metadata-field-identifiers</a></p>\n<a href=\"#fnref-13\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-14\">\n<p>Processing Notify Callouts <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-notify-callouts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-notify-callouts</a></p>\n<a href=\"#fnref-14\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-15\">\n<p>Processing Classify Callouts Asynchronously <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-classify-callouts-asynchronously\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/processing-classify-callouts-asynchronously</a></p>\n<a href=\"#fnref-15\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-16\">\n<p>FwpsPendOperation0 function (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpspendoperation0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpspendoperation0</a></p>\n<a href=\"#fnref-16\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-17\">\n<p>FwpsCompleteOperation0 function (fwpsk.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpscompleteoperation0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpscompleteoperation0</a></p>\n<a href=\"#fnref-17\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-18\">\n<p>Filtering condition flags <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/filtering-condition-flags\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/filtering-condition-flags</a></p>\n<a href=\"#fnref-18\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-19\">\n<p>Types of Callouts <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/types-of-callouts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/network/types-of-callouts</a></p>\n<a href=\"#fnref-19\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-20\">\n<p>KeWaitForSingleObject function (wdm.h) <a href=\"https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/wdm/nf-wdm-kewaitforsingleobject\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/wdm/nf-wdm-kewaitforsingleobject</a></p>\n<a href=\"#fnref-20\" class=\"footnote-backref\">↩</a>\n</li>\n<li id=\"fn-21\">\n<p>Pending Connection Reauthorization <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/fwp/ale-re-authorization#pending-connection-reauthorization\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://learn.microsoft.com/ja-jp/windows/win32/fwp/ale-re-authorization#pending-connection-reauthorization</a></p>\n<a href=\"#fnref-21\" class=\"footnote-backref\">↩</a>\n</li>\n</ol>\n</div>","fields":{"slug":"/a-part-of-anti-virus-3-03-en","tagSlugs":["/tag/a-part-of-anti-virus-3-en/","/tag/windows-en/","/tag/win-dbg-en/","/tag/anti-virus-en/","/tag/english/"]},"frontmatter":{"date":"2026-04-11","description":"This is the web edition of A PART OF ANTI-VIRUS 3 distributed at Technical Book Fest 20.","tags":["A PART OF ANTI-VIRUS 3 (en)","Windows (en)","WinDbg (en)","AntiVirus (en)","English"],"title":"A PART OF ANTI-VIRUS 3 - Learning Windows Filtering Platform (WFP) from Public Sample Code - (WEB Edition) [Chapter 3: A Sample That Uses a Callout Driver for Access Control]","socialImage":{"publicURL":"/static/272acc1e889df0e25d89217e89d5fd13/a-part-of-anti-virus-3.png"}}}},"pageContext":{"slug":"/a-part-of-anti-virus-3-03-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}