I recently had a co-worker ask me what the best way to find an object matching certain criteria in an STL vector. We talked about the “old-school” ways of doing that, like a for loop from zero to the number of items, or a for loop using the being and end iterators. Each of these would do the comparison and then break out of the loop if a match was found. Now these ways work just fine, but there are some newer, more “modern” methods of accomplishing the same things that use STL algorithms. In case you haven’t seen them before I thought I would share…

The first method uses a structure/class to wrap the comparison function and is usually called a “functor”. Essentially this is just an object that implements operator(), which allows you to treat the object somewhat like a function. (And you can pass it to other functions like STL algorithms.)

The second method uses the more modern “lambda” function syntax. It allows you to just define the comparison function right inline with the code. This is the one that I prefer because it keeps the comparison logic with the calling of the find algorithm. I think one of the most important aspects of good code is that it’s easy to follow and understand: you shouldn’t have to go skipping all over the code to figure out what some piece of code is doing.

Of course at first glance, a programmer who is unfamiliar with either of these methods is going to respond “huh?” But once you get used to seeing a functor or a lambda expression, they become pretty easy to read and understand.

So without further ado, on to the code, which demonstrates a very simple example of each method:
Continue reading

I ran into an interesting case while working on a registry filter driver the other day. Boiled down to its most basic form, my driver is blocking access to registry keys by name. I watch for a name that matches one in my list then fail the open/create. The interesting case is when a registry key is a symbolic link (I.e., was created with REG_CREATE_LINK and has a REG_LINK value named SymbolicLinkValue that points to a second key).

All my filtering work takes place in the Pre-Open/Create path, and because the name coming in doesn’t actually represent what really will be opened, I can’t exactly rely on the name. So after digging into how these operations get handled, I have found some very odd behavior. I see two different behaviors for an open/create under these conditions. I created a sample filter driver to test this and tested on Windows 8 x64 and Windows 7 x64.

  1. When I try to open the link source (the key that links to a second key), I see the following:
  1. RegNtPreOpenKeyEx with CompleteName containing the name of the key – I return STATUS_SUCCESS to allow processing to continue.
  2. RegNtPostOpenKeyEx with PreInformation->CompleteName containing the key name from the SymbolicLinkValue. Status contains STATUS_REPARSE.
  3. RegNtPreOpenKeyEx with Complete Name containing the key name of the link target (from step b).
  4. RegNtPostOpenKeyEx with Status equal to STATUS_SUCCESS.
  • After a small number of repetitions (usually 2) the above behavior stops, and is replaced with the following:
    1. RegNtPreOpenKeyEx with CompleteName containing the name of the key – I return STATUS_SUCCESS to allow processing to continue.
    2. RegNtPostOpenKeyEx with Status equal to STATUS_SUCCESS. PreInformation->CompleteName contains the original name from step a, but the Object contains a pointer to a registry object for the link target key.

    Additionally, the behaviors above seem to revert after some period of time. If I run a simple registry open command for the link source a hundred times, I see behavior #1 twice and then #2 the remainder of the time. But after doing that if I let the machine sit idle for 4-5 minutes and run it again, I will again see behavior #1 twice, followed by #2 for as many times as I care to repeat it.

    I e-mailed some contacts at Microsoft and they confirmed what I have been seeing. The registry maintains a key lookup cache that is intended to speed up open/create operations. One thing that the cache can do is remember symbolic links and avoid the need to reparse them every time they are opened. This is a bit frustrating for me, but it probably makes a significant difference in registry performance (which, incidentally is a heck of a lot faster than file system performance).

    Unfortunately it would seem that the way to solve this problem is to store some of the data I need internally to my driver based on watching the systems behavior. So, for example, I can watch for the STATUS_REPARSE result to come back, and do something with the CompleteName value. So I could add a context to the call in the pre-open, put the original complete name in the context, then in the post-open when I see STATUS_REPARSE, I can add an entry to a list that says “Name A links to Name B”, which I can thereafter use in my pre-open. I then also have to deal with cases where the link key gets removed (I can watch for a pre-open with OBJ_OPENLINK, place a context on the object, then watch for the delete, and clean up my internal cache). I also have to deal with the case where the link gets retargeted to something else (I can watch for the pre-open with OBJ_OPENLINK, context the object, watch for the pre-set-value for REG_LINK named SymbolicLinkValue and update my cache).

    I won’t show the solution code here, since its fairly complicated, and it is the intellectual property of my company, but the solution is fairly straight-forward once you understand what needs to be done. I will, however, show some of the code that I actually used to test this and grok the behavior.

    Continue reading

    Windows Installer stores information about components, products, etc. that are installed on the system in the registry. Most of these elements are identified by a GUID, but the Installer doesn’t always store the GUID directly in the registry. Instead it uses what I call SQUIDs, or Squished GUIDs. Basically they just reformat the GUID a bit and remove some of the extra characters that don’t add anything (hyphens and braces). You can read more about this here: A Brief Note on Installer GUIDs.

    Periodically when I am working on some installer code I can end up needing to search the registry for stuff that is related to a component I am working on. It is very helpful to be able to convert between SQUIDs and GUIDs. I usually just do this by hand, but today I decided I needed a bit more help doing this and wrote a tiny vbscript piece of code that does the conversion. On the chance that it might provide value for someone else, I have decided to post it here.

    Function SquidToGuid(s)
      SquidToGuid = _
        StrReverse(Mid(s, 1, 8)) & "-" & _
        StrReverse(Mid(s, 9, 4)) & "-" & _
        StrReverse(Mid(s, 13, 4)) & "-" & _
        StrReverse(Mid(s, 17, 2)) & StrReverse(Mid(s, 19, 2)) & "-" & _
        StrReverse(Mid(s, 21, 2)) & StrReverse(Mid(s, 23, 2)) & StrReverse(Mid(s, 25, 2)) & _
        StrReverse(Mid(s, 27, 2)) & StrReverse(Mid(s, 29, 2)) & StrReverse(Mid(s, 31, 2))
    End Function
    
    Function GuidToSquid(g)
      Replace g, "{", ""
      Replace g, "}", ""
      GuidToSquid = _
        StrReverse(Mid(g, 1, 8)) & _
        StrReverse(Mid(g, 10, 4)) & _
        StrReverse(Mid(g, 15, 4)) & _
        StrReverse(Mid(g, 20, 2)) & StrReverse(Mid(g, 22, 2)) & _
        StrReverse(Mid(g, 25, 2)) & StrReverse(Mid(g, 27, 2)) & StrReverse(Mid(g, 29, 2)) & _
        StrReverse(Mid(g, 31, 2)) & StrReverse(Mid(g, 33, 2)) & StrReverse(Mid(g, 35, 2))
    End Function

    So I was troubleshooting a bug with a co-worker the other day and what we were seeing was a little confusing, and it turned out to be a difference in when I/O gets pended in the system. The basic scenario was that we were calling ZwQueryDirectoryFile to do some testing of a filter driver that was changing the directory query results. In testing without the driver installed, the return value from ZwQueryDirectoryFile was always STATUS_PENDING. So the assumption was made that this would continue to always be true.

    Well as soon as our filter was installed and we changed the results of the query, the api started returning immediately. Our code was assuming that then I/O would be pending and was waiting on the handle and checking the IoStatusBlock for the results, and it just wasn’t looking correct: the IoStatusBlock was showing STATUS_SUCCESS when we thought our filter had returned STATUS_NO_SUCH_FILE. After figuring out what was going on, I thought I would write a bit about how pending I/O works in the kernel.

    When an API call is made, there are times when it can be immediately determined what result should be returned. For example, if you pass a bad parameter, the system doesn’t need to pend the I/O because it can return STATUS_INVALID_PARAMETER immediately. In this case, ZwQueryDirectoryFile would just return STATUS_INVALID_PARAMETER as its result, and the IoStatusBlock should be ignored.

    If the API call returns STATUS_PENDING, only then should the caller wait on the handle to be signaled and then check the value of the IoStatusBlock parameter to determine the outcome of the I/O operation.

    In our specific case, our filter driver was populating the results and returning STATUS_NO_SUCH_FILE. This was changing the behavior of the test call to ZwQueryDirectoryFile from sending the request to disk and pending the I/O (the behavior without our driver) to returning the status code immediately.

    So it seems that a correct way to call one of these functions should look something like the following:

    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS status = ZwQueryDirectoryFile( ... );
    if ( STATUS_PENDING == status )
    {
       ZwWaitForSingleObject( ... );
       status = IoStatusBlock.Status;
    }
    // Do something with the result of the query directory call
    

    Today I had to implement a service that used directory notification to watch for changes in a directory and then handle each change by migrating it to another location. I went back to my previous post about directory notification and used some of the code there to implement what I needed. Unfortunately, the code in that post for processing the returned data is not quite right. It skips that last entry in the returned buffer, which in practice means it skips most of the entries, since it is most common for there to be a single entry in the buffer.

    Following is a code segment that processes the entries correctly.
    Continue reading

    I have had a number of situations over the last five years where I have had to write code that detects changes made in a directory. Some has been for testing my own directory notification code at the file-system level, and others have been for real implementation reasons up in usermode code.

    The documentation can be a lot to wade through as there are a number of different ways that such notification can be accomplished. I won’t go into the reasons for using each (check MSDN documentation for some information on that), but I wanted to post some simple samples of using each for anyone who might be interested.

    There are five different methods, using Win32 APIs, that are used in this sample. They don’t do anything special except print out basic information about the changes that are detected.
    Continue reading