{"id":411,"date":"2009-08-18T16:32:21","date_gmt":"2009-08-18T16:32:21","guid":{"rendered":"https:\/\/driverentry.com.br\/en\/2009\/08\/18\/notifying-events-to-the-application\/"},"modified":"2026-07-31T00:14:49","modified_gmt":"2026-07-31T00:14:49","slug":"notifying-events-to-the-application","status":"publish","type":"post","link":"https:\/\/driverentry.com.br\/en\/2009\/08\/18\/notifying-events-to-the-application\/","title":{"rendered":"Notifying events to the application"},"content":{"rendered":"<div style=\"text-align: right;\"><a href=\"https:\/\/driverentry.com.br\/2009\/08\/18\/notificando-eventos-a-aplicacao\/\"><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>A few weeks ago, here I was all tangled up with my college project. With all this activity, what I have been telling my friends is that my <a href=\"http:\/\/twitter.com\/driverentry\">Twitter<\/a> looks more like a schedule. But anyway, in the middle of so much rush, I received the following question from reader J\u00c3\u00balio C\u00c3\u00a9sar (Rio de Janeiro &#8211; RJ):<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;How do you implement communication between a driver and an application such that the driver initiates the communication? That is, I do not want the application to send a message to the driver, but rather the driver to send a message to the application.&#8221;<\/span><\/p>\n<\/blockquote>\n<p>My short but blunt answer is that there are no means for a driver to simply wake up on a sunny morning, scratch its belly while stretching and say to itself: <span style=\"font-style: italic;\">&#8220;Today I am going to surprise my friend notepad.exe. I am going to send it a postcard from Kernel-land.&#8221;<\/span><\/p>\n<h3>A Client-Server model<\/h3>\n<p>Windows works on a Client-Server model, where the Server side would be the Kernel, which serves the requests of its clients, which in this case are the applications. No activity is initiated by the Kernel of its own free will. It is always the applications that, using the system&#8217;s native API, request notifications from the system for a series of events.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;But Fernando, what about the plug-and-play notifications to user-mode applications?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>Actually they are requested by the applications using the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa363431(VS.85).aspx\">RegisterDeviceNotification()<\/a> routine. This subject is quite nice to comment on in a future post. Let me jot it down here on my list of posts to write.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;But Fernando, when the system starts, do not things start automagically?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>The Boot is a special procedure in which the Kernel starts only the Session Manager in User-land, also known among the close ones as <span style=\"font-weight: bold;\">Smss<\/span>. <span style=\"font-style: italic;\">Smss<\/span> is a native process (which uses only the native API) and is considered a trusted component. It does not use the Windows API because the Windows Subsystem (<span style=\"font-weight: bold;\">Csrss<\/span>) does not exist yet. From there on a series of initializations originated by <span style=\"font-style: italic;\">Smss<\/span> and its child processes occurs, but I will leave the details about this to the <a href=\"http:\/\/www.caloni.com.br\/blog\/archives\/o-boot-no-windows-sem-windows\">Slug<\/a>. That reminded me that <span style=\"font-style: italic;\">Csrss<\/span> stands for <span style=\"font-style: italic;\">&#8220;Client Server Run-Time Subsystem&#8221;<\/span>.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;But Fernando, what about the services?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>Services are started by a process called <span style=\"font-style: italic;\">Services.exe<\/span>, which in turn was also started by another component during the Boot process.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;But Fernando, what about the boot drivers?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>The loading of drivers is not considered a notification to user-mode.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;But Fernando, does it rain in September?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>Well, that is enough, right? Let us talk about what matters now.<\/p>\n<h3>Pending I\/O operations<\/h3>\n<p>We have already seen in <a href=\"https:\/\/driverentry.com.br\/en\/2008\/06\/07\/creating-and-using-ioctls\/\">another post<\/a> that an application can request services from the driver. To give the impression that the driver sent a notification to the application, we can use an operation that would remain pending until the desired event occurs. Such as a read operation on a serial port, which would remain stuck in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa365467(VS.85).aspx\">ReadFile()<\/a> call until one or more characters were received.<\/p>\n<p>This works reasonably well, but we would have some complications if the event never occurs and your application needs to leave because it left the beans on the stove or something like that. So, we would have to adopt a <span style=\"font-style: italic;\">multi-threaded<\/span> solution, where a second thread would warn the pending thread that it is too late, that there is no point in waiting for the event anymore, it is over, meow, forget it, get real.<\/p>\n<p>For the people who suffer from <span style=\"font-style: italic;\">&#8220;thread-phobia&#8221;<\/span>, a solution using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms686358(VS.85).aspx\">Overlapped I\/O<\/a> would fit like a glove, but I am not going to talk about that today. Actually that is already on my list, but it is not going to be today.<\/p>\n<h3>Sharing an event<\/h3>\n<p>The way I most like to work is by sharing an event. Does everyone know what an event is? It may seem silly, but there are a lot of people who do not really know what a <span style=\"font-style: italic;\">handle <\/span>is and want to program the Kernel. That worries me a little. What kind of drivers can these people generate? Allow me to open a parenthesis here to ask a question: What do you think about, besides me offering driver posts, me offering posts about <span style=\"font-style: italic;\">System Programming<\/span>? Things like Processes, Threads, Objects, Handles, Virtual Memory, Heaps, Dispatch Objects, Synchronization and so on. Send me e-mails with suggestions, which will be very welcome.<\/p>\n<p>Getting back to what matters, if an application creates an event and sends its handle to the driver, the driver will be able to signal the existence of relevant information to the application. So the application can wait for this event, and when it is signaled, the application does the I\/O to fetch such information using the means of communication we have already seen in <a href=\"https:\/\/driverentry.com.br\/en\/2008\/10\/16\/buffered-direct-or-neither-in-ioctls\/\">other posts<\/a>.<\/p>\n<h3>Image Notifier<\/h3>\n<p>To exemplify the reception of events generated by a driver, today we are going to see a driver that will warn us whenever an image is mapped in a process.<\/p>\n<p>First we are going to define an interface for this communication. The application will need to send the handle of an event to the driver; this will also tell the driver that the application wishes to receive notifications about image mapping. For that we are going to define our IOCTLs as we already saw <a href=\"https:\/\/driverentry.com.br\/en\/2008\/06\/07\/creating-and-using-ioctls\/\">in this other post<\/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;\"><span style=\"color: green;\">\/\/-f--&gt; This will be the IOCTL to notify the driver that an<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      application is interested in the image load<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      events. This IOCTL must carry the handle of the event<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      to be signaled when there is data for the application.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#define<\/span> IOCTL_IMG_START_NOTIFYING   CTL_CODE(FILE_DEVICE_UNKNOWN,   \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                             <span style=\"color: purple;\">0x800<\/span>,                 \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                             METHOD_BUFFERED,       \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                             FILE_ANY_ACCESS)<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/-f--&gt; I know it is silly to create a structure with a single member,<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      but besides being more didactic, this makes it easier for that<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      crowd that is going to do \"Copy and Paste\" of my code into<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      other projects. Later they will want to send more data<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      to the driver and will get tangled up with it. And then you know whose<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      fault it is: \"I got this code on that fool's blog!\".<\/span><\/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> _IMG_START_NOTIFYING<\/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;\">    HANDLE  hEvent;<\/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;\">} IMG_START_NOTIFYING, *PIMG_START_NOTIFYING;<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/-f--&gt; This will be the IOCTL that the application will send to the driver to<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      get the details about the image load in a process.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: blue;\">#define<\/span> IOCTL_IMG_GET_IMAGE_DETAIL  CTL_CODE(FILE_DEVICE_UNKNOWN,   \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                             <span style=\"color: purple;\">0x801<\/span>,                 \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                             METHOD_BUFFERED,       \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                             FILE_ANY_ACCESS)<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/-f--&gt; Here I am going to define a maximum path of 260 characters, but<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      there may be cases of longer paths. I am not going to handle<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      all the cases nor optimize the transport of this buffer<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      by taking only the valid bytes.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: blue;\">#define<\/span> IMG_MAX_IMAGE_NAME  <span style=\"color: purple;\">260<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/-f--&gt; Here follows the path of the image that the driver will obtain<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      before notifying the application.<\/span><\/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> _IMG_IMAGE_DETAIL<\/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;\">    CHAR    ImageName[IMG_MAX_IMAGE_NAME];<\/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;\">} IMG_IMAGE_DETAIL, *PIMG_IMAGE_DETAIL;<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/-f--&gt; Here the application says it is no longer interested in the<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: green;\">\/\/      image notifications. This will make the driver<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\"><span style=\"color: green;\">\/\/      release the reference it made to the handle.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\"><span style=\"color: blue;\">#define<\/span> IOCTL_IMG_STOP_NOTIFYING    CTL_CODE(FILE_DEVICE_UNKNOWN,   \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                             <span style=\"color: purple;\">0x802<\/span>,                 \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                             METHOD_BUFFERED,       \\<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                             FILE_ANY_ACCESS)<\/pre>\n<\/div>\n<p>I am not going to put all the code here in the post, but it is all available in the example for download at the end of this post. Remember that nine out of ten dentists recommend reading the comments for a better understanding of the example. The application will basically create an event and send its handle to the driver through an IOCTL.<\/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;\">    \/\/-f--&gt; Creates the event that will be shared.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    hNotificationEvt = CreateEvent(NULL,<\/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;\">                                   FALSE,<\/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;\">    _ASSERT(hNotificationEvt);<\/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;\">    printf(<span style=\"color: #a31515;\">\"Requesting device to start notifying.\\n\"<\/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 copy the event handle into the structure<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      that will be sent to the driver. As we know, handles<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      are valid only in the context of this process,<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      so we are assuming that our driver will be<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      at the top of the device stack.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    StartNotifying.hEvent = hNotificationEvt;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: blue;\">if<\/span> (!DeviceIoControl(hDevice,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         IOCTL_IMG_START_NOTIFYING,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         &amp;StartNotifying,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                         <span style=\"color: blue;\">sizeof<\/span>(StartNotifying),<\/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: purple;\">0<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                         &amp;dwBytes,<\/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;\">    {<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/-f--&gt; Take a deep breath and open WinDbg...<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        dwError = GetLastError();<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        printf(<span style=\"color: #a31515;\">\"Error #%d on starting device notification.\\n\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">               dwError);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">__leave<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    }<\/pre>\n<\/div>\n<p>When the driver receives this IOCTL, it will acquire a reference to the object pointed to by the handle. Note that for this the driver uses the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms802942.aspx\">ObReferenceObjectByHandle()<\/a> routine of the Object Manager, which besides incrementing the object&#8217;s reference counter, also certifies that the handle is of the object type you expect to receive. This would prevent, for some reason, the handle of another object from being passed in place of the event handle. The result of this call will be a pointer to an event received by the driver. As we know, objects have their header in a standard format, but the body of the object varies depending on its type. Imagine that someone sent a handle to a thread in place of a handle to an event; we could use the event routines to manipulate a thread and the chance of everything going blue is high. That is why the use of the <span style=\"font-style: italic;\">ObjectType<\/span> parameter, although optional, is highly recommended.<\/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;\">\/\/-f--&gt; Gets a reference to the object<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    nts =  ObReferenceObjectByHandle(pStartNotifying->hEvent,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                     EVENT_ALL_ACCESS,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                     *ExEventObjectType,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                     UserMode,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                     (PVOID*)&amp;g_pEvent,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                     NULL);<\/pre>\n<\/div>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;Fernando, is this really necessary? My application is the only one that is going to use this driver, and it will always send a handle to an event.&#8221;<\/span><\/p>\n<\/blockquote>\n<p>This kind of precaution prevents a smart-aleck program from sending anything to your driver, deliberately producing a blue screen.<\/p>\n<blockquote>\n<p><span style=\"font-weight: bold; font-style: italic;\">&#8220;Fernando, in my opinion what you really like is to complicate things. Couldn&#8217;t I simply make a copy of the handle and use routines like <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd851996.aspx\">ZwSetEvent()<\/a> that receive the event handle as a parameter?&#8221;<\/span><\/p>\n<\/blockquote>\n<p>Look, the handle is valid only within the process that obtained it. In our case, that handle is valid only in the context of our test application. Image notifications run in an arbitrary context, that is, God knows in which process context. That is why we will have to obtain a reference that is valid in any context. The pointer obtained by the <span style=\"font-style: italic;\">ObReferenceObjectByHandle()<\/span> routine is valid in any context, because it points to the object itself, which resides in <span style=\"font-weight: bold;\">System Space<\/span>. If you do not know what <span style=\"font-style: italic;\">System Space<\/span> means, then take a stroll through <a href=\"https:\/\/driverentry.com.br\/en\/2008\/09\/11\/a-pinch-of-virtual-memory\/\">this post<\/a>.<\/p>\n<p>Well, after that the application is going to keep waiting for the event to be signaled by the driver. In the code below, two events are monitored; one of them is signaled by the driver while the other is signaled by the application itself at the moment of ending its activity.<\/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;\">\/\/-f--&gt; Here we create an array of handles to wait<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      for multiple objects.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    hObjects[<span style=\"color: purple;\">0<\/span>] = hFinishEvt;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    hObjects[<span style=\"color: purple;\">1<\/span>] = hNotificationEvt;<\/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;\">do<\/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; Waits either for a signal from the device indicating the<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      presence of data in the driver, or a signal from the<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      primary thread saying that soap-opera<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      nonsense and stuff.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        dwWait = WaitForMultipleObjects(<span style=\"color: purple;\">2<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                        hObjects,<\/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;\">                                        INFINITE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">switch<\/span>(dwWait)<\/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;\">case<\/span> WAIT_FAILED:<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: green;\">\/\/-f--&gt; Come on, Murphy, give it a rest!<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            dwError = GetLastError();<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            printf(<span style=\"color: #a31515;\">\"Error #%d on waiting for device notification.\\n\"<\/span>,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                   dwError);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: blue;\">__leave<\/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;\">case<\/span> WAIT_OBJECT_0 + <span style=\"color: purple;\">1<\/span>:<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: green;\">\/\/-f--&gt; Whoa! The driver has something for us, let us go get it.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: blue;\">if<\/span> (GetImageDetail(hDevice) != ERROR_SUCCESS)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                <span style=\"color: blue;\">__leave<\/span>;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            <span style=\"color: blue;\">break<\/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;\">&nbsp;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/-f--&gt; We will stay in this while the termination event<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      is not signaled by the primary thread.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    } <span style=\"color: blue;\">while<\/span>(dwWait != WAIT_OBJECT_0);<\/pre>\n<\/div>\n<p>When the event is signaled, the application will send an IOCTL to get the data from the driver. Our test application also prints this data on the screen for pure fun. Let us take a look at the driver&#8217;s code to find out how this happens.<\/p>\n<p>During initialization, the driver calls the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms802949.aspx\">PsSetLoadImageNotifyRoutine()<\/a> routine to register a callback routine that is called whenever an image is mapped to some process.<\/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;\">\/\/-f--&gt; Registers a callback routine to receive<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      the notifications of images mapped to<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      processes.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    nts = PsSetLoadImageNotifyRoutine(OnLoadImage);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ASSERT(NT_SUCCESS(nts));<\/pre>\n<\/div>\n<p>Our callback routine converts the path of the mapped image from Unicode to ANSI. More details about string conversion in <a href=\"https:\/\/driverentry.com.br\/en\/2009\/07\/07\/strings-in-the-kernel\/\">this post<\/a>. Next the routine places this path in a list and sets the event sent by the application. If you still do not know how to play with linked lists in the Windows kernel, then read <a href=\"https:\/\/driverentry.com.br\/en\/2007\/02\/24\/linked-lists-on-ddk\/\">this post<\/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;\">VOID<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">OnLoadImage(IN PUNICODE_STRING  pusFullImageName,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">            IN HANDLE           hProcessId,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            IN PIMAGE_INFO      pImageInfo)<\/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;\">    PIMG_EVENT_NODE pNode;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    ANSI_STRING     asImageName;<\/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 are going to acquire control of the variables<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      shared by different threads.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    nts = KeWaitForMutexObject(&amp;g_EventMtx,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                               UserRequest,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                               KernelMode,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                               FALSE,<\/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;\">    ASSERT(NT_SUCCESS(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: 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; Checks whether the application is interested in this<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      event.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: blue;\">if<\/span> (!g_pEvent)<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: blue;\">__leave<\/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; Allocates a node for the list of image paths<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pNode = (PIMG_EVENT_NODE)ExAllocatePoolWithTag(PagedPool,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                                       <span style=\"color: blue;\">sizeof<\/span>(IMG_EVENT_NODE),<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                                       IMG_TAG);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: blue;\">if<\/span> (!pNode)<\/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;\">            ASSERT(FALSE);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: blue;\">__leave<\/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; Initializes an ANSI_STRING to use in the conversion<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      of the image path. We will always provide one byte<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        <span style=\"color: green;\">\/\/      less to reserve space for adding a<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      null terminator.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        RtlInitEmptyAnsiString(&amp;asImageName,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                               pNode->ImageDetail.ImageName,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                               <span style=\"color: blue;\">sizeof<\/span>(pNode->ImageDetail.ImageName) - <span style=\"color: purple;\">1<\/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; Does the conversion without allocating the result.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = RtlUnicodeStringToAnsiString(&amp;asImageName,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                           pusFullImageName,<\/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; Oops!<\/span><\/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;\">            ExFreePool(pNode);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">            <span style=\"color: blue;\">__leave<\/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; Places the null terminator so that the test<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      application can count on it when doing the print.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        asImageName.Buffer[asImageName.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; Inserts the node into the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        InsertTailList(&amp;g_ListHead,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                       &amp;pNode->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; We set the event informing the application that there is<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        <span style=\"color: green;\">\/\/      data in the list to be read.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        KeSetEvent(g_pEvent,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                   IO_NO_INCREMENT,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                   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;\">    <span style=\"color: blue;\">__finally<\/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; Finally, releases the mutex and runs for the hug.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeReleaseMutex(&amp;g_EventMtx,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                       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;\">}<\/pre>\n<\/div>\n<p>When the event is signaled, the application wakes up from its deep sleep and finds out that the driver has data for it. So it sends an IOCTL to get such data. This IOCTL will execute the routine below, removing the first element of the list and checking whether there is still more data to be collected by the application. If the list empties in this call, the driver resets the event so that the application goes back to sleep waiting for the records of newly mapped images.<\/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;\">OnGetImageDetail(PIMG_IMAGE_DETAIL  pImageDetail)<\/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;<\/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;\">    PIMG_EVENT_NODE pNode;<\/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; Acquires the mutex<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    nts = KeWaitForMutexObject(&amp;g_EventMtx,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                               UserRequest,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                               KernelMode,<\/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;\">                               NULL);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    ASSERT(NT_SUCCESS(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; Checks whether the list is empty. Always<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      use this routine before trying to remove<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      an element from the list.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">if<\/span> (!IsListEmpty(&amp;g_ListHead))<\/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; Gets the address of the Entry<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        pEntry = RemoveHeadList(&amp;g_ListHead);<\/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; Gets the address of the node<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        pNode = CONTAINING_RECORD(pEntry,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                                  IMG_EVENT_NODE,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                                  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; Copies to the application buffer.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        RtlCopyMemory(pImageDetail,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">                      &amp;pNode->ImageDetail,<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">                      <span style=\"color: blue;\">sizeof<\/span>(IMG_IMAGE_DETAIL));<\/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 node and that's that<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">        ExFreePool(pNode);<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        nts = STATUS_SUCCESS;<\/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;\">        nts = STATUS_NO_MORE_ENTRIES;<\/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; It may be that in this call the list has<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      become empty. So we check again<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: green;\">\/\/      and reset the event so that the application<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">    <span style=\"color: green;\">\/\/      does not come back here.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    <span style=\"color: blue;\">if<\/span> (IsListEmpty(&amp;g_ListHead))<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">        KeResetEvent(g_pEvent);<\/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; Releases the mutex and that's it.<\/span><\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FAFAFA;\">    KeReleaseMutex(&amp;g_EventMtx,<\/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;\">return<\/span> nts;<\/pre>\n<pre style=\"margin: 0px; padding: 0 0 0 5px; background: #FFFFFF;\">}<\/pre>\n<\/div>\n<h3>The result of so much blah-blah-blah<\/h3>\n<p>After the driver is compiled, installed and started, we will be able to run our test application and wait for something to be executed. When a process is created, both its module and the DLLs it depends on are mapped in the system. This will trigger our callback routine in the driver and make the whole thing work. If you do not know how to compile, install and start a driver, <a href=\"https:\/\/driverentry.com.br\/en\/2006\/09\/11\/getting-started\/\">this post<\/a> may help you.<\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" src=\"https:\/\/driverentry.com.br\/en\/wp-content\/uploads\/2026\/07\/ImgNotifier.png\" alt=\"\" \/><\/div>\n<p><br class=\"spacer_\" \/><\/p>\n<p>The image above is the result of running <span style=\"font-style: italic;\">notepad.exe<\/span> while our test application was waiting for events, but any other process could trigger such events. This post, besides providing us with this example of an inverted call, also shows us how to play with <span style=\"font-weight: bold;\">Mutex Objects<\/span>, which was the question of another reader, Ismael Rocha (Bras\u00c3\u00adlia &#8211; DF).<\/p>\n<p>Now let me get back to my college project.<br \/>\n See you!<\/p>\n<p class=\"download\"><a href=\"http:\/\/www.driverentry.com.br\/samples\/ImgNotifier.zip\">ImgNotifier.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few weeks ago, here I was all tangled up with my college project. With all this activity, what I have been telling my friends is that my Twitter looks more like a schedule. But anyway, in the middle of so much rush, I received the following question from reader J\u00c3\u00balio C\u00c3\u00a9sar (Rio de Janeiro [&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-411","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/411","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=411"}],"version-history":[{"count":2,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/411\/revisions"}],"predecessor-version":[{"id":413,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/posts\/411\/revisions\/413"}],"wp:attachment":[{"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/media?parent=411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/categories?post=411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/driverentry.com.br\/en\/wp-json\/wp\/v2\/tags?post=411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}