{"id":404,"date":"2009-07-07T12:01:55","date_gmt":"2009-07-07T12:01:55","guid":{"rendered":"https:\/\/driverentry.com.br\/en\/2009\/07\/07\/strings-in-the-kernel\/"},"modified":"2026-07-30T22:52:49","modified_gmt":"2026-07-30T22:52:49","slug":"strings-in-the-kernel","status":"publish","type":"post","link":"https:\/\/driverentry.com.br\/en\/2009\/07\/07\/strings-in-the-kernel\/","title":{"rendered":"Strings in the Kernel"},"content":{"rendered":"<div style=\"text-align: right;\"><a href=\"https:\/\/driverentry.com.br\/2009\/07\/07\/strings-no-kernel\/\"><img loading=\"lazy\" decoding=\"async\" title=\"Em Portugues\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/br.gif\" alt=\"\" width=\"21\" height=\"19\" \/><\/a><\/div>\n<p>Is there anything more trivial than manipulating strings? I believe the correct answer would be &#8220;<span style=\"font-style: italic;\">It depends<\/span>&#8220;. When I had finished my technical course in Industrial Computing in 1995, I thought I knew a lot about the C language. After all, I already knew how to manipulate strings. Copy, concatenate, reverse, search for words&#8230; What else should a programmer know? When I started my internship and began dealing with real-world programs, I found out that I knew nothing. But one thing is certain, I knew how to manipulate strings. This post should help a lot the C++ programmers who know everything about <a href=\"http:\/\/en.wikipedia.org\/wiki\/Template_(programming)\">Templates<\/a>, <a href=\"http:\/\/en.wikipedia.org\/wiki\/Smart_pointer\">Smart Pointers<\/a>, <a href=\"http:\/\/en.wikipedia.org\/wiki\/Standard_Template_Library\">STL<\/a> and magical things that abstract reality, making the programmer&#8217;s life easier. With all these reference-counting resources and overloading of every operator there is, things start to get hazy and you begin to wonder: <span style=\"font-style: italic;\">&#8220;But where is the buffer, really?&#8221;<\/span>. Today we are just going to take a light stroll through the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa492030.aspx\">UNICODE_STRING<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa491546.aspx\">ANSI_STRING<\/a> structures and some functions for converting between them. It may seem silly, but if you do not know how to play with strings, why learn the rest? It is all going to end in a blue screen anyway.<\/p>\n<h3>And back in kindergarten&#8230;<\/h3>\n<p>We learned from the teacher back in kindergarten that strings are chains of characters. So we could tell the story of our lives just by placing one character in front of another.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">CHAR    szExemplo[] = <span style=\"color: #a31515;\">\"Tava ruim l\u00e1 na Bahia, profiss\u00e3o de b\u00f3ia-fria\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"Trabalhando noite e dia, num era isso que eu queria\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      <span style=\"color: #a31515;\">\"Eu vim-me embora pra \\\"Sum Paulo\\\",\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"Eu vim no lombo dum jumento com pouco conhecimento\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      <span style=\"color: #a31515;\">\"Enfrentando chuva e vento e dando uns peido fedorento (vish)\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"At\u00e9 minha bunda fez um calo\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      <span style=\"color: #a31515;\">\"Chegando na capital, uns puta predi\u00e3o legal\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"As mina pagando um pau, mas meu jumento tava mal\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      <span style=\"color: #a31515;\">\"Precisando reformar\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"Fiz a pintura, importei quatro ferradura\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      <span style=\"color: #a31515;\">\"Troquei at\u00e9 dentadura e pra completar a belezura\\n\"<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"Eu instalei um Road-Star!\"<\/span>;<\/pre>\n<\/div>\n<p><span style=\"font-style: italic;\">Jumento Celestino \/ Mamonas Assassinas<\/span><\/p>\n<p>There are two things you must know so that you can keep reading this post. One of them is that these characters need to be stored somewhere, whether in a local variable, allocated on the heap or even in the initialized data segment. The other thing is that strings are normally terminated by a NULL character, but the absence of it does not disqualify a string. This means we can have strings without terminators where their size is indicated by another variable. I leave here a <a href=\"http:\/\/www.caloni.com.br\/blog\/archives\/strings\">hook<\/a> for the Slug to explain these things to the interested boys and girls.<\/p>\n<p>Another important characteristic is that a character is not always equal to a Byte. There are strings composed of wide characters. Wide characters, contrary to what people think, are not lucky characters, but rather characters formed by 16-bit values. With strings formed by such characters, one can express words in any language. This explains how Windows manages to deal with alien file names when you try to install the drivers for the <a href=\"http:\/\/www.youtube.com\/watch?v=M3mbLGjTfhU\">HiPhone<\/a> you bought in Chinatown.<\/p>\n<p>Besides, imagine that an error occurs during the encryption process of your hard drive. It would be vital that a detailed error message be displayed to you regardless of the nationality of the product. Whether the information is going to help is another matter.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/chinese_error.jpg\" alt=\"\" \/><\/div>\n<h3>Four types of strings<\/h3>\n<p>Of these, we have two strings that we are already used to seeing in user-Mode, both terminated with a NULL character.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">CHAR    szString[] = <span style=\"color: #a31515;\">\"Uma string de CHAR\"<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">WCHAR   wzString[] = L<span style=\"color: #a31515;\">\"Uma string de WCHAR\"<\/span>;<\/pre>\n<\/div>\n<p>The other two strings are the ones we normally see in kernel-mode.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">typedef<\/span> <span style=\"color: blue;\">struct<\/span> _UNICODE_STRING {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  USHORT  Length;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">  USHORT  MaximumLength;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  PWSTR  Buffer;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">} UNICODE_STRING, *PUNICODE_STRING;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">typedef<\/span> <span style=\"color: blue;\">struct<\/span> _STRING {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  USHORT  Length;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">  USHORT  MaximumLength;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  PCHAR  Buffer;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">} ANSI_STRING, *PANSI_STRING;<\/pre>\n<\/div>\n<p>These strings are defined by structures with three members, which I describe below. The behavior of the routines and macros that manipulate them is very similar. For this reason I am going to concentrate my examples on UNICODE_STRING, since the Win32 subsystem converts everything to unicode when it passes a call to the kernel.<\/p>\n<ul>\n<li>\n<p><strong>Buffer:<\/strong> It is a pointer to the region of memory where the characters are stored.<\/p>\n<\/li>\n<li>\n<p><strong>Length:<\/strong> Indicates the number of valid bytes of the string. This size is always expressed in bytes, even if this is a WCHAR string.<\/p>\n<\/li>\n<li>\n<p><strong>MaximumLength: <\/strong>Indicates the maximum size this string can have.<\/p>\n<\/li>\n<\/ul>\n<p>To understand how these members are interpreted, take a look at the example below:<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">void<\/span> OsTresMembros(<span style=\"color: blue;\">void<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    WCHAR           wsUmArray[<span style=\"color: purple;\">200<\/span>];<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    UNICODE_STRING  usString;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--> I indicate where the characters of this string<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      will be stored.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    usString.Buffer = wsUmArray;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We have not written anything in the buffer yet,<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      so nothing that is in the buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      is valid.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    usString.Length = <span style=\"color: purple;\">0<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Even though the buffer is not initialized<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      it is still there and can hold a string<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      of at most its size in bytes.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    usString.MaximumLength = <span style=\"color: blue;\">sizeof<\/span>(wsUmArray);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<p>Here we see an empty unicode string, since it has zero valid bytes, but its storage capacity is up to 200 characters. Note that the characters are stored in an array that is on the stack. This means that no memory <span style=\"font-style: italic;\">leak<\/span> will be caused by the ending of this routine.<\/p>\n<h3>Initializing Strings<\/h3>\n<p>We can also use some macros that do the initialization of these structures.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">void<\/span> InitString(<span style=\"color: blue;\">void<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    UNICODE_STRING  usOutraConstante;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    UNICODE_STRING  usVazia;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    WCHAR           wzBuffer[<span style=\"color: purple;\">30<\/span>] = L<span style=\"color: #a31515;\">\"Isso n\u00e3o ser\u00e1 considerado.\"<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Initializes a string at its creation.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    UNICODE_STRING  usConstante = RTL_CONSTANT_STRING(L<span style=\"color: #a31515;\">\"Uma string.\"<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Initializes a constant string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlInitUnicodeString(&amp;usOutraConstante,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         L<span style=\"color: #a31515;\">\"Uma outra string constante que n\u00e3o muda.\"<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Initializes an empty string for later use<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlInitEmptyUnicodeString(&amp;usVazia,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                              wzBuffer,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                              <span style=\"color: blue;\">sizeof<\/span>(wzBuffer));<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<p>Note the values of these structures.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> ?? usConstante<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">struct _UNICODE_STRING<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> \"Uma string.\"<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   +0x000 Length           : 0x16<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">   +0x002 MaximumLength    : 0x18<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   +0x004 Buffer           : 0xf8cd8600  \"Uma string.\"<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">kd> db 0xf8cd8600 L0x18<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">f8cd8600  55 00 6d 00 61 00 20 00-73 00 74 00 72 00 69 00  U.m.a. .s.t.r.i.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">f8cd8610  6e 00 67 00 2e 00 00 00                          n.g.....<\/pre>\n<\/div>\n<p>Although the maximum capacity of this string is 0x18 characters, only 0x16 bytes are valid. That is because the macro disregards the NULL terminator that the C\/C++ compiler left as a bonus.<\/p>\n<p>The <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa906838.aspx\">RTL_CONSTANT_STRING()<\/a> macro lets us initialize the string at its creation, but another notable feature of it is that it screws up the IntelliSense of Visual Studio (2008 at least). So if you really like IntelliSense, prefer to use the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms802969.aspx\">RtlInitUnicodeString()<\/a> macro.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> ?? usVazia<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">struct _UNICODE_STRING<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"> \"Isso n\u00e3o ser\u00e1 considerado.\"<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   +0x000 Length           : 0<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">   +0x002 MaximumLength    : 0x3c<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   +0x004 Buffer           : 0xf8ae5c34  \"Isso n\u00e3o ser\u00e1 considerado.\"<\/pre>\n<\/div>\n<p>Oops! How can a string with zero valid bytes be displayed by WinDbg? Actually, what happens is that WinDbg takes the UNICODE_STRING structure apart and shows each of the members here. In this case, there is an array of WCHAR with well-behaved values here. Do not blame the poor thing. You are the one who is spoiled by Visual Studio.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> db 0xf8ae5c34 L0x3c<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">f8ae5c34  49 00 73 00 73 00 6f 00-20 00 6e 00 e3 00 6f 00  I.s.s.o. .n...o.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">f8ae5c44  20 00 73 00 65 00 72 00-e1 00 20 00 63 00 6f 00   .s.e.r... .c.o.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">f8ae5c54  6e 00 73 00 69 00 64 00-65 00 72 00 61 00 64 00  n.s.i.d.e.r.a.d.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">f8ae5c64  6f 00 2e 00 00 00 00 00-00 00 00 00              o...........<\/pre>\n<\/div>\n<p>But this data is only there by chance. It is not considered part of a valid unicode string. This gets in the way a bit when debugging, because even the local variables window also shows this invalid content.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/usLocals.png\" alt=\"\" \/><\/div>\n<p><br class=\"spacer_\" \/><\/p>\n<p>The <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/cc266940.aspx\">!ustr<\/a> extension shows only the valid data of a unicode string.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> !ustr usConstante<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">String(22,24) at f899fc6c: Uma string.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">kd> !ustr usVazia<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">String(0,60) at f8ae5c1c:<\/pre>\n<\/div>\n<h3>Is the terminator necessary?<\/h3>\n<p><img decoding=\"async\" style=\"float: right; margin: 0px 10px;\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/terminator.png\" border=\"0\" alt=\"\" \/><\/p>\n<p>Not at all! You can well observe that in the previous examples, the macro left the terminator out of the valid bytes. Considering the terminator as a valid byte is a mistake and can cause confusion. Imagine comparing two distinct strings that carry the same content, but one of them considers the terminator as valid information. Such strings will be different, since they have a different length.<\/p>\n<p>I believe what really matters is not to count on the terminator in the strings you receive from other components. It is a fact that most of the time, the buffer has a terminator, and that even though it is not considered valid information, the terminator is still there. Never count on that unless there is some note in the documentation. I have seen people use the <span style=\"font-style: italic;\">Buffer<\/span> member as a parameter for a call to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/78zh94ax(VS.80).aspx\">wcslen()<\/a> routine, for example. Besides the risk of getting incorrect information, there is also a bonus of possibly generating a blue screen.<\/p>\n<p><span style=\"font-weight: bold;\"><span style=\"font-style: italic;\">&#8220;But Fernando, I have already tested this on several operating systems and it always worked.&#8221;<\/span><\/span><\/p>\n<p>That does not justify anything; you cannot rely on tests, but on documentation. When your product spreads across the market, it faces many different environments, with the most diverse filters, anti-viruses, monitors and so on. You cannot be sure of the implementation of any software. The best we can hope from them is that they rely on the documentation.<\/p>\n<h3>Manipulating Strings<\/h3>\n<p>The members of the UNICODE_STRING structure are basically used by manipulation routines in order to check whether the existing buffer is enough for the desired operation. Therefore, before using a string, make sure it was initialized correctly. In the case of a string copy, the destination string will need to be initialized even if empty.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">void<\/span> CopyString(<span style=\"color: blue;\">void<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    UNICODE_STRING  usSource;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    UNICODE_STRING  usTarget;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    WCHAR           wzTarget[<span style=\"color: purple;\">10<\/span>];<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Here we initialize our source string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    RtlInitUnicodeString(&amp;usSource,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         L<span style=\"color: #a31515;\">\"12345678901234567890\"<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Here we initialize our destination string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    RtlInitEmptyUnicodeString(&amp;usTarget,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                              wzTarget,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                              <span style=\"color: blue;\">sizeof<\/span>(wzTarget));<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Performs the copy<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlCopyUnicodeString(&amp;usTarget,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         &amp;usSource);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<p>Here we see the example of a string copy where the source string is larger than the destination one. In that situation we will not have an access violation, but the destination buffer will be filled completely. Note that the routine did not leave us the comfortable terminator.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> !ustr usTarget<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">String(20,20) at f89a3c6c: 1234567890<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">kd> ?? usTarget<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">struct _UNICODE_STRING<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"> \"1234567890\"<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">   +0x000 Length           : 0x14<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">   +0x002 MaximumLength    : 0x14<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">   +0x004 Buffer           : 0xf89a3c54  \"1234567890\"<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">kd> db 0xf89a3c54 L0x20<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">f89a3c54  31 00 32 00 33 00 34 00-35 00 36 00 37 00 38 00  1.2.3.4.5.6.7.8.<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">f89a3c64  39 00 30 00 98 5d 5f 00-14 00 14 00 54 3c 9a f8  9.0..]_.....T&lt;..<\/pre>\n<\/div>\n<p>Unlike the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms803010.aspx\">RtlCopyUnicodeString()<\/a> routine, some other routines return STATUS_BUFFER_TOO_SMALL to us when the buffer is insufficient.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">VOID <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  RtlCopyUnicodeString(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN OUT PUNICODE_STRING  DestinationString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PCUNICODE_STRING  SourceString<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    );<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">NTSTATUS <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  RtlAppendUnicodeStringToString(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN OUT PUNICODE_STRING  Destination,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PUNICODE_STRING  Source<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    );<\/pre>\n<\/div>\n<p>There is a series of string manipulation routines in the WDK, but there is always some routine missing compared to the broad library of routines of the C\/C++ standard library. Routines like <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ftw0heb9(VS.71).aspx\">strrchr()<\/a> for example. When necessary we will have to build a version that manipulates UNICODE_STRING structures in the same way. Here is a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms796247.aspx\">basic list of string routines<\/a> that the WDK supports. Other functions are listed <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa489561.aspx\">here<\/a>, but we will talk about them later.<\/p>\n<h3>But where is the buffer, really?<\/h3>\n<p>The UNICODE_STRING structure does not store a buffer, but rather a pointer to it. This way, the manner of discarding a string varies depending on the way you obtained it. In the examples we have seen so far, the buffers used are in initialized data or in local arrays of the example function. There are routines that initialize and allocate strings as a way of returning the desired information. In these cases, it is necessary to free the buffer you received. This is the case of the routines that do the conversion from ANSI_STRING to UNICODE_STRING and vice versa. They are <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms803001.aspx\">RtlUnicodeStringToAnsiString()<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms804316.aspx\">RtlAnsiStringToUnicodeString().<\/a><\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">NTSTATUS <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">  RtlAnsiStringToUnicodeString(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN OUT PUNICODE_STRING  DestinationString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PANSI_STRING  SourceString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN BOOLEAN  AllocateDestinationString<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    );<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">NTSTATUS <\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">  RtlUnicodeStringToAnsiString(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN OUT PANSI_STRING  DestinationString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN PUNICODE_STRING  SourceString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN BOOLEAN  AllocateDestinationString<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    );<\/pre>\n<\/div>\n<p>The example below does a conversion from ANSI to UNICODE with allocation of the result, and then frees the received buffer.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">void<\/span> ConvertString(<span style=\"color: blue;\">void<\/span>)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ANSI_STRING     asString;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    UNICODE_STRING  usString;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Here we initialize our source string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlInitAnsiString(&amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: #a31515;\">\"Um exemplo simples.\"<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; In this case we will not need to initialize the<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/     destination string. The routine will do that for us.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    RtlAnsiStringToUnicodeString(&amp;usString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                 &amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                 TRUE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Prints the resulting string<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    DbgPrint(<span style=\"color: #a31515;\">\"String convertida: %wZ\\n\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">             &amp;usString);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We free the buffer allocated in the conversion.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlFreeUnicodeString(&amp;usString);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<p>You yourself can write a routine that generates UNICODE_STRINGs by allocating the buffer dynamically. The buffer can be allocated dynamically using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms796989.aspx\">ExAllocatePoolWithTag()<\/a> or one of its sisters. However, when freeing the buffer of this string, use the appropriate function, which in this example would be <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms796854.aspx\">ExFreePoolWithTag()<\/a>. Do not go around using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms804310.aspx\">RtlFreeUnicodeString()<\/a> left and right. Enjoy in moderation. Only use that routine to free strings that were obtained by functions like <span style=\"font-style: italic;\">RtlAnsiStringToUnicodeString()<\/span>, whose documentation indicates the use of <span style=\"font-style: italic;\">RtlFreeUnicodeString()<\/span>.<\/p>\n<p><span style=\"font-style: italic;\"> <\/span><\/p>\n<blockquote>\n<p><span style=\"font-weight: bold;\">&#8220;&#8230;, the caller must deallocate the buffer by calling RtlFreeUnicodeString.&#8221;<\/span><\/p>\n<\/blockquote>\n<h3>Safe Strings in Kernel<\/h3>\n<p>A portion of the string manipulation routines of the C\/C++ standard library, such as <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/kk6xf663.aspx\">strcpy()<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ybk95axf(VS.71).aspx\">sprintf()<\/a>, are also available in the kernel, but the growing concern with security in buffer manipulation caused the safe functions to be made available both for user-mode and for kernel-mode. For details on the use of these functions consult <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa489591.aspx\">this link<\/a>.<\/p>\n<h3>One more example driver<\/h3>\n<p>This <a href=\"https:\/\/driverentry.com.br\/en\/2007\/06\/18\/we-want-samples\/\">other post<\/a> brings the example of a driver that keeps a list of strings in memory. In this <a href=\"https:\/\/driverentry.com.br\/en\/2007\/08\/29\/using-fileobject-and-fscontext\/\">other post<\/a>, that same example was evolved so that different lists were kept under different contexts. Now I am going to evolve that example again. The application will keep sending NULL-terminated strings during the write, the driver will create ANSI_STRINGs from them and convert them into UNICODE_STRINGs before placing them in the list.<\/p>\n<p>Most of the modifications are in the read and write routines, so I am just going to show the code of these routines here. In any case, the whole project including the driver and a test application are available for download at the end of this post. Let us start with the write routine that sends the strings to the driver. As always, all the relevant information is in the comments.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     OnWrite<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      The application is sending a string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">*\/<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">NTSTATUS<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">OnWrite(IN PDEVICE_OBJECT  pDeviceObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        IN PIRP            pIrp)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PIO_STACK_LOCATION  pStack;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ANSI_STRING         asString;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PSTRING_LIST        pStringList;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PSTRING_REG         pStringReg;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ULONG               ulBytes;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    KIRQL               kIrql;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    NTSTATUS            nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We get the current Stack Location.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    pStack = IoGetCurrentIrpStackLocation(pIrp);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Gets the head of the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pStringList = (PSTRING_LIST)pStack->FileObject->FsContext;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; What we have in the system buffer here is an array<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      of NULL-terminated bytes. We are going to initialize<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      an ANSI_STRING with this buffer.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RtlInitAnsiString(&amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      (PCSZ)pIrp->AssociatedIrp.SystemBuffer);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Here we allocate the node that will be placed in the list<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    pStringReg = (PSTRING_REG) ExAllocatePoolWithTag(NonPagedPool,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                                     <span style=\"color: blue;\">sizeof<\/span>(STRING_REG),<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                                     STR_LST_TAG);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; To do the conversion to UNICODE_STRING, we are going to<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      ask the routine to make the allocation of the resulting<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      buffer. For this reason, we will not need to initialize<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      the output string.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    nts = RtlAnsiStringToUnicodeString(&amp;pStringReg->usString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                       &amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                       TRUE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Oops! We probably did not have memory for that.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      We will signal the failure and inform the IoManager<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      that zero bytes were copied.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ExFreePoolWithTag(pStringReg, STR_LST_TAG);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pIrp->IoStatus.Information = <span style=\"color: purple;\">0<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">else<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; We will hold the spinlock to avoid contention<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      on access to the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeAcquireSpinLock(&amp;pStringList->SpinLock,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                          &amp;kIrql);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Inserts the node into the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        InsertTailList(&amp;pStringList->ListHead,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                       &amp;pStringReg->Entry);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Releases the spinlock.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeReleaseSpinLock(&amp;pStringList->SpinLock,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                          kIrql);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Here we inform the IoManager that all the bytes<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      sent by the application were received<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      successfully by the driver.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pIrp->IoStatus.Information = pStack->Parameters.Write.Length;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; The Information field was already filled in, we will just<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      copy the status of the operation and complete the IRP.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    pIrp->IoStatus.Status = nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IoCompleteRequest(pIrp, IO_NO_INCREMENT);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<p>Now let us look at the retrieval of the strings on the read.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/****<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">***     OnRead<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      The application wants to receive the strings sent<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      by it.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">*\/<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">NTSTATUS<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">OnRead(IN PDEVICE_OBJECT  pDeviceObj,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">       IN PIRP            pIrp)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ANSI_STRING         asString;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PIO_STACK_LOCATION  pStack;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PSTRING_LIST        pStringList;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PSTRING_REG         pStringReg;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PLIST_ENTRY         pEntry;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    KIRQL               kIrql;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    NTSTATUS            nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; We will leave this field at zero until we are<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      sure that the copy was made to the application<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pIrp->IoStatus.Information = <span style=\"color: purple;\">0<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We get the current Stack Location.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    pStack = IoGetCurrentIrpStackLocation(pIrp);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Gets the head of the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pStringList = (PSTRING_LIST)pStack->FileObject->FsContext;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We will return to the application only an array of CHAR<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      with a NULL terminator. The strings are stored as<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      UNICODE_STRING. We will convert them to ANSI_STRING.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      Here we will initialize the ANSI_STRING that will receive<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      the result of the UNICODE_STRING conversion.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; We will offer Length-1 to reserve a byte for<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      the null terminator after conversion.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    RtlInitEmptyAnsiString(&amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                           (PCHAR)pIrp->AssociatedIrp.SystemBuffer,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                           (USHORT)pStack->Parameters.Read.Length - <span style=\"color: purple;\">1<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; Here we will acquire the spinlock to avoid contention<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      on access to the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    KeAcquireSpinLock(&amp;pStringList->SpinLock,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      &amp;kIrql);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/-f--&gt; Checks whether the list is empty.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">if<\/span> (IsListEmpty(&amp;pStringList->ListHead))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Signals an error on the read and releases the spinlock right away.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = STATUS_NO_MORE_ENTRIES;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeReleaseSpinLock(&amp;pStringList->SpinLock,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                          kIrql);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">else<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Removes the record from the list and releases the spinlock right away.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pEntry = RemoveHeadList(&amp;pStringList->ListHead);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        KeReleaseSpinLock(&amp;pStringList->SpinLock,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                          kIrql);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pStringReg = CONTAINING_RECORD(pEntry,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                       STRING_REG,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                       Entry);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Here we convert the string. Note that we do not request<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      the allocation of the buffer. We are using the system<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      buffer to receive the result of the conversion. In this<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      case the destination string must be initialized.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = RtlUnicodeStringToAnsiString(&amp;asString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                           &amp;pStringReg->usString,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                           FALSE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: green;\">\/\/-f--&gt; Here we use that byte we reserved and thus<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: green;\">\/\/      the null terminator is also copied by the IoManager<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: green;\">\/\/      from the SystemBuffer to the application buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            asString.Buffer[asString.Length] = <span style=\"color: purple;\">0<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: green;\">\/\/-f--&gt; We need to tell the IoManager the number of<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: green;\">\/\/      bytes that will be copied to the application buffer.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: green;\">\/\/      That size is the size of the converted string plus<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: green;\">\/\/      one byte taken by the NULL terminator we placed.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            pIrp->IoStatus.Information = asString.Length+<span style=\"color: purple;\">1<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; In this example, we are not handling the error case<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      in the conversion, which can happen if the application sends<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      a small buffer for the string. If any error occurs<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      during the conversion, we will simply discard the string<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Frees the string's buffer and then the record it<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      occupied in the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        RtlFreeUnicodeString(&amp;pStringReg->usString);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ExFreePoolWithTag(pStringReg, STR_LST_TAG);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/-f--&gt; The Information field was already filled in, we will just<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      copy the status of the operation and complete the IRP.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    pIrp->IoStatus.Status = nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IoCompleteRequest(pIrp, IO_NO_INCREMENT);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">}<\/pre>\n<\/div>\n<p>With this driver running, I can already think of some filter examples. I have been thinking about filter examples for some time, besides receiving post suggestions on this subject. The fact is that we did not have a basis for it. The important thing is to have a driver simple enough for the easy understanding of things. There is no point in me making a post with a hard-disk filter, a network filter or any other driver with plug-and-play and power management. Those would need a lot of accumulated knowledge and would not fit in a post.<\/p>\n<p>Anyway, once again I hope I have helped. And if any doubt arises, just send me an e-mail.<\/p>\n<p>Have fun!<\/p>\n<p class=\"download\"><a href=\"http:\/\/www.driverentry.com.br\/samples\/StringList.zip\">StringList.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Is there anything more trivial than manipulating strings? I believe the correct answer would be &#8220;It depends&#8220;. When I had finished my technical course in Industrial Computing in 1995, I thought I knew a lot about the C language. After all, I already knew how to manipulate strings. Copy, concatenate, reverse, search for words&#8230; What [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-404","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/404","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/comments?post=404"}],"version-history":[{"count":3,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/404\/revisions"}],"predecessor-version":[{"id":407,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/404\/revisions\/407"}],"wp:attachment":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/media?parent=404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/categories?post=404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/tags?post=404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}