Zach Burlingame
Programming, Computers, and Other Notes on Technology

Archive for the ‘Uncategorized’ Category

Getting the Load Count for a DLL

Wednesday, August 17th, 2011

Recently I was trying to unload a DLL from a running process so that I could delete it from the disk but it just wouldn’t delete. Looking at the Modules pane in Visual Studio, I could see that the DLL was still loaded. I doubled and tripled check all of my calls to LoadLibrary for a corresponding call to FreeLibrary, and everything checked out. I needed to figure out what was loading it and where. One of the things that I wanted to know was, “What is the current load count for the DLL?”

Windows maintains a load count for each module on a per-process basis. When the load count reaches zero, the module will be unloaded. The problem is that this load count is not accessible through documented API calls. To get it, you need to use some undocumented structures and API calls from ntdll.dll. Fortunately, like so many other issues you run into, someone else has already run into it and Google knows where they are at. In this case there is a great article here (unfortunately I couldn’t figure out who specifically was the contributing author for that article so that I could give them due props).

The securityxploded article did such a great job of explaining it that I won’t bother to duplicate it here. I based my implementation on theirs however I updated it to support both MBCS and Unicode via the TCHAR macros. It’s available as part of my ModuleUtilities library.

Signal a Windows Application to Terminate from Another Process

Tuesday, April 12th, 2011

In usual fashion, I’ve written a complete sample application. The source code is available here.

Sometimes you want detect if a specific application is running and signal it to terminate in a clean manner. It may be your upgrade installer making sure that the current version of the application is not running before performing it’s upgrade. It could be a long running helper process that needs to be signaled when it is no longer needed. Whatever it is, one method to accomplish this is to use a uniquely named shared event.

NOTE: The method I’m about describe only works for processes who’s source code is under your control. If you want a way to generically signal any running process (e.g. search for a list of running OS and 3rd-party processes that might interfere with your installer and signal them to terminate) then this is not what you want.

A Bit of Background

A similar problem to the one we are discussing here is signaling all running threads to terminate. The idea is that there could be multiple places in the code where an application might need to initiate a process termination, but you need to synchronize that across all threads and allow them to perform their own cleanup. One way to do this is have long running threads periodically check to see if they should shutdown by checking to see if an event is signaled.

Windows Events

On the Windows platform when an event object is created it is done so in an object namespace. In addition to the ability to create your own private namespaces, there are also two special kernel object namespaces – Global and Local. There is a Local namespace associated with each client session on the machine. By default the Local namespace is used for any object created by a process that was started under a client session. As the name implies, there is a single Global namespace system-wide. The Global namespace is used primarily by system services but can also be used by client session processes by prefixing the event name with “Global\”.

The CreateEvent function is used to (surprise!) create an event. It can create either a named or unnamed event. If you use a named event and the named event already exists before the call to CreateEvent then the function returns a handle to the existing object and GetLastError returnsĀ ERROR_ALREADY_EXISTS. By creating a named event, the OS enforces that only a single instance of the object exists in that namespace at any one time and that all processes referring to that event will receive a handle to the same instance, creating a form of interprocess communication. Thus if the Local namespace is used, then the event object is shared across all processes that refer to it in that client session. Likewise if it is created in the Global namespace, it is shared across all processes that refer to it on the entire system.

There are two reset mechanisms used by event objects: AutoReset and ManualReset. An AutoReset event will automatically be reset to a non-signaled state as soon as single waiting thread is released. A ManualReset event requires a call to ResetEvent in order to be returned to a non-signaled state.

Lastly, an event can be set to either the signaled or non-signaled state when it is initially created.

Signal Terminate via Named Event Object

By combining the concept of checking for a signaled event to determine when to shutdown and using a named event object, it is possible to signal one process to shutdown via another process. By using an event object created in the Local namespace you can signal processes across a single client session. Conversely by using an event object created in the Global namespace you can signal processes across the entire system.

When creating the terminate event object you want to use a ManualReset event created in the non-signaled state initially. If it were instead an AutoReset event, then as soon as one of the waiting threads from any of the processes was released, the event would return to the non-signaled state. This would result in only a single thread receiving the terminate message, which is not what we want. As for the state, if it were instead initially signaled then the threads would begin terminating as soon as they started running and began checking the event.

Below is an example of creating a named ManualReset event in the Local object namespace that is intially non-signaled. I’m using a GUID for the object name to avoid the potential for unintentional naming collisions with other applications. While a GUID is probably overkill, using a name like “shutdown_event” probably isn’t a good idea.

static const LPCSTR fp_terminate_event_name =
   "Local\\0BAF85D0-0786-4cbf-AF3B-E36322382DBF";

// Create a manual-reset event in the non-signaled state
fh_terminate_event =
  CreateEvent( NULL,                              // default security attributes
               TRUE,                              // manual-reset event.
               FALSE,                             // initial state is non-signaled
               TEXT( fp_terminate_event_name ) ); // object name