{"id":318,"date":"2008-06-23T16:38:29","date_gmt":"2008-06-23T16:38:29","guid":{"rendered":"https:\/\/driverentry.com.br\/en\/2008\/06\/23\/using-the-registry-part-2\/"},"modified":"2026-07-29T14:41:25","modified_gmt":"2026-07-29T14:41:25","slug":"using-the-registry-part-2","status":"publish","type":"post","link":"https:\/\/driverentry.com.br\/en\/2008\/06\/23\/using-the-registry-part-2\/","title":{"rendered":"Using the Registry (Part 2)"},"content":{"rendered":"<div style=\"text-align: right;\"><a href=\"https:\/\/driverentry.com.br\/2008\/06\/23\/utilizando-o-registry-parte-2\/\"><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>Well, as I was saying in the <a href=\"https:\/\/driverentry.com.br\/en\/2008\/06\/16\/using-the-registry-part-1\/\">first part of this post<\/a>. That is a lot of code. This whole thing looks like a lot of work, doesn&#8217;t it? Building a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa492030.aspx\">UNICODE_STRING<\/a> for the path of the key you want to access, building an <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa491657.aspx\">OBJECT_ATTRIBUTES<\/a> with it, opening a handle, determining the size of the values to be read, allocating a large enough buffer, reading the value you want, freeing any temporary buffer used in the process, and finally closing the handle to the registry key. You can check how much code we used in our <a href=\"https:\/\/driverentry.com.br\/samples\/KernelReg.zip\">example from the previous post<\/a> to read two values from the registry. Today we will look at a group of registry-manipulation routines that make this process easier.<\/p>\n<h3>RTL Registry Routines<\/h3>\n<p>There are only five routines that make up this little group. <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa489620.aspx\">In the reference<\/a> you will find a description of each one. A common trait of this group of routines is that we do not have to use handles for the keys. The handles are opened and closed for each operation. Another common trait is that you do not need to compose the full name of the key where the values you want to read or write are. These routines work with a key-name scheme relative to some pre-defined place. Confusing? Let us take a look at one of the routines so we have a more practical example. Trying to follow the same idea as the example given in the previous post, we first need to check whether the key where the values are stored actually exists. There is a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms804317.aspx\">little function<\/a> just for that.<\/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;\">  RtlCheckRegistryKey(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN ULONG  RelativeTo,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PWSTR  Path<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    );<\/pre>\n<\/div>\n<p>Note that the first parameter of this routine is a constant that indicates what reference will be applied to the second parameter. Look at the table below, which was taken from the reference.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/RegRefTable.png\" alt=\"\" \/><\/div>\n<p>An example would be the following: If we use RTL_REGISTRY_ABSOLUTE as the first parameter, the second must be the full path of the registry key. After all, we have to pass the key&#8217;s absolute path. On the other hand, if we use RTL_REGISTRY_SERVICES, the second parameter should be only the path complement relative to the <em>Services<\/em> key. That was the option I used in this post&#8217;s example. See how our routine for creating the parameters in the registry turned out.<\/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;\">***     CreateParams<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      This routine is called when the key that contains<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      the parameters is not detected. It creates the key and the parameters<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      with pre-defined values.<\/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;\">CreateParams(VOID)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    NTSTATUS        nts = STATUS_SUCCESS;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    WCHAR           wzParam[] = L<span style=\"color: #a31515;\">\"DriverEntry.com.br\"<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ULONG           ulParam = <span style=\"color: purple;\">0x12345678<\/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: blue;\">__try<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Create the key where the parameters will be stored.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      Just like that.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = RtlCreateRegistryKey(RTL_REGISTRY_SERVICES,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                   L<span style=\"color: #a31515;\">\"KernelReg2\\\\Parameters\"<\/span>);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExRaiseStatus(nts);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Here we write the numeric value<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                    L<span style=\"color: #a31515;\">\"KernelReg2\\\\Parameters\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                    L<span style=\"color: #a31515;\">\"DoubleWord\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                    REG_DWORD,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                    &amp;ulParam,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                    <span style=\"color: blue;\">sizeof<\/span>(ulParam));<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExRaiseStatus(nts);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; And here the String. Note that it was not necessary<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      to create a UNICODE_STRING for this.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                    L<span style=\"color: #a31515;\">\"KernelReg2\\\\Parameters\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                    L<span style=\"color: #a31515;\">\"String\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                    REG_SZ,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                    wzParam,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                    <span style=\"color: blue;\">sizeof<\/span>(wzParam));<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">__except<\/span>(EXCEPTION_EXECUTE_HANDLER)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Oops!<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = GetExceptionCode();<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ASSERT(FALSE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/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>Once again, the code shown here is available for download at the end of this post.<\/p>\n<h3>When easy gets complicated<\/h3>\n<p>From what we have seen so far, this group of routines has already made our life a little easier. But it is in the read routine that we can see the code savings really happen. The cost of that comes down to understanding how the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms803008.aspx\">read routine<\/a> works.<\/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;\">  RtlQueryRegistryValues(<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN ULONG  RelativeTo,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PCWSTR  Path,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN PRTL_QUERY_REGISTRY_TABLE  QueryTable,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    IN PVOID  Context,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    IN PVOID  Environment  OPTIONAL<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    );<\/pre>\n<\/div>\n<p>Looking at it like this, it does not even seem like it bites, but if you take a look at the reference, you will see it can be quite flexible. Flexibility is sometimes translated as <em>&#8220;Hard to get the right way to use it&#8221;<\/em>. The first two parameters are the ones already known from before. Things start to change with the third parameter, which is a table that contains the details of the values to be read from the registry. I will not go into the details of each parameter of this routine in this post. I will just write the code equivalent to the previous post&#8217;s example.<\/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;\">***     LoadParams<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">**      This routine loads the global variables with the<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">**      values retrieved from the registry.<\/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;\">LoadParams(VOID)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">{<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    NTSTATUS                    nts = STATUS_SUCCESS;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    RTL_QUERY_REGISTRY_TABLE    QueryTable[] =<\/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;\">        { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">          L<span style=\"color: #a31515;\">\"DoubleWord\"<\/span>, &amp;g_ulParam, REG_NONE, NULL, <span style=\"color: purple;\">0<\/span> },<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">          L<span style=\"color: #a31515;\">\"String\"<\/span>, &amp;g_usParam, REG_NONE, NULL, <span style=\"color: purple;\">0<\/span> },<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        { NULL, <span style=\"color: purple;\">0<\/span>, NULL, NULL, REG_NONE, <span style=\"color: purple;\">0<\/span>, NULL }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    };<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">__try<\/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; If this routine is called more than once, let's free<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      the buffer of this parameter.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">if<\/span> (g_usParam.Buffer)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            RtlFreeUnicodeString(&amp;g_usParam);<\/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 all the table's values are read<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                     L<span style=\"color: #a31515;\">\"KernelReg2\\\\Parameters\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                     QueryTable,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                     NULL,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                     NULL);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!NT_SUCCESS(nts))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            ExRaiseStatus(nts);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    }<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">__except<\/span>(EXCEPTION_EXECUTE_HANDLER)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; Oops!<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        nts = GetExceptionCode();<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        ASSERT(FALSE);<\/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: blue;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<p>No, nothing is missing. That is really all there is. Let us take a closer look at what we did here. The table we filled in has the data for the reads to be performed and is defined as shown below.<\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: #A4F64C; border: 1px outset; padding: 0 0 0 5px;\">\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">typedef<\/span> <span style=\"color: blue;\">struct<\/span> _RTL_QUERY_REGISTRY_TABLE {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ULONG Flags;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    PWSTR Name;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PVOID EntryContext;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ULONG DefaultType;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    PVOID DefaultData;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ULONG DefaultLength;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;<\/pre>\n<\/div>\n<p>Looking at each of its members we have:<\/p>\n<ul>\n<li><strong>QueryRoutine:<\/strong> Here you have a function pointer that will be called when this table item is read from the registry. We do not use this method in our example. There are some interesting things about this callback routine. It is called for each item of this table, but if the value to be read is of type REG_MULTI_SZ, the callback routine is called once for each string contained in that value. Check the reference for a complete description of these details.<\/li>\n<li><strong>Flags:<\/strong> The flag we used here was RTL_REGISTRY_DIRECT, which signals that we will not use the callback method. Another flag is RTL_QUERY_REGISTRY_REQUIRED, which indicates that the value described in this table row is required. If the value is not found, RtlQueryRegistryValues returns an error and the remaining values will not be read.<\/li>\n<li><strong>Name:<\/strong> Here comes the name of the value to be read. Note that it is not a UNICODE_STRING, but a zero-terminated WCHAR array.<\/li>\n<li><strong>EntryContext:<\/strong> In our example, this parameter is the buffer where the read value will be stored, but in the cases where we get the call through the callback routine, this value is passed as one of the parameters.<\/li>\n<\/ul>\n<p>The parameters <strong>DefaultType<\/strong>, <strong>DefaultData<\/strong> and <strong>DefaultLengh<\/strong> would be used if the value did not exist and was not a required value.<\/p>\n<p>Each value to be read is represented by a row in this table. The routine identifies the end of the table when it finds the <em>QueryRotuine<\/em> and <em>Name<\/em> members set to NULL.<\/p>\n<p><strong>Hold on, Fernando! All right, nothing up this sleeve, nothing up that one, and the values just get read? Clever you, huh? Thought you would fool everyone with that little chat? All right! Where do I indicate the size of the buffer offered for the read?<\/strong><\/p>\n<p>Very good question! I do not think even I would have asked such a good one. The buffer size is indicated by the buffer itself. In the case of the string, we pass a pointer to a UNICODE_STRING; the size of the string&#8217;s buffer is already described by that structure, but if the buffer of this structure is NULL, the routine allocates a buffer of the needed size. We have to free that buffer when we are no longer going to use it. For reads where the resulting buffer is smaller than or equal to sizeof(ULONG), the resulting value is stored directly in the place pointed to by EntryContext. For further details, consult the reference.<\/p>\n<p>This function is quite flexible and I will not be able to put everything this routine offers into a single post, but feel free to send your questions about it.<\/p>\n<p>Have fun!<\/p>\n<p class=\"download\"><a href=\"http:\/\/www.driverentry.com.br\/samples\/KernelReg2.zip\">KernelReg2.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Well, as I was saying in the first part of this post. That is a lot of code. This whole thing looks like a lot of work, doesn&#8217;t it? Building a UNICODE_STRING for the path of the key you want to access, building an OBJECT_ATTRIBUTES with it, opening a handle, determining the size of the [&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-318","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/318","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=318"}],"version-history":[{"count":5,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/318\/revisions"}],"predecessor-version":[{"id":323,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/318\/revisions\/323"}],"wp:attachment":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/media?parent=318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/categories?post=318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/tags?post=318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}