Assumptions
This article assumes a basic understanding of writing unmanaged C/C++ dynamic link libraries and exporting functions from those libraries. Also basic understanding of using P/Invoke to access unmanaged libraries will benefit the reader, but I will attempt to explain as much as possible.
Abstract
The purpose of this article is to discuss several problems a developer might face when attempting to mix unmanaged and managed code. A problem that is all too often encountered when attempting to interact with the current Windows API from a managed language such as C# or VB.NET. In this article, I will discuss the problems I faced and how I solved the problems using a combination of managed and unmanaged code, C# and VC++ respectively. Here is a brief overview of what you can learn by reading this article:
- Calling unmanaged function pointers
- Dynamically loading unmanaged libraries at runtime
- Acquiring function pointers to unmanaged functions
- Translating C/C++ structures and data types to CLR compliant code
- Finding alternatives to unsafe code for the purposes of using sizeof
- Allocating/deallocating memory on the stack
- Understanding how applets can be manipulated programmatically
- Extracting strings and icons from embedded resources located in external unmanaged libraries.
Background
So let's begin by discussing why I decided to write this article and code. Being the curious coder I am, I am always intrigued by the underlying implementation of features in the Windows operating system. Control panel applets have always been a somewhat uncovered topic for some reason, yeah there is documentation on them in the MSDN library, but rarely any good working examples. Let along how they actually work. Before I set out to write this article, I already had a pretty good understanding of how applets are written, having written several as a professional developer in the past. However, it wasn't until I stepped into shell development that I became completely curious just how Windows pulled off these wonderfully useful creatures.
As days went by developing my shell, I came across many methods for actually launching control panel applets from code. Most of the implementations involved hard coding references to rundll32.exe to call the Control_RunDLL
function with various arguments to launch off control panel applets. This always bothered me, because this was far from dynamic, you had to know about the applets ahead of time, at least somewhat to figure out how to launch them. I decided I wanted a means to enumerate and host the applets just like Windows.
So having said the why, let's discuss what an applet actually is. By the way, all of the information presented here is my personal dissection of the documentation found in the MSDN library. Control panel applets are nothing special, simply .dll s built with a special extension, .cpl , and placed into the Windows system directory. If you were to attempt to write one, you would have to choose a language that creates unmanaged DLLs and allows for exporting of unmanaged functions. Something that C# and VB just don't do, so look to C++ or Delphi to pull this off. It's not all that hard, but it's beyond the scope of the article.
Now that we know what an applet is, an unmanaged DLL compiled with a .cpl extension, let's look at how they work. Digging into the documentation, you will discover the CplApplet function. It is the sole function an applet must export from its library to interface with Windows. The function looks like this:
LONG CPlApplet(HWND hWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
The function is very similar to the WndProc functions behind all windows. All communication to applets occurs through this function. You do not need to understand anything more about this function for now. If you are interested, do a search for CPlApplet in the MSDN library and you will have the pleasure of translating this wonderful function just as the rest of us were forced to do.
Ok, so let's review what we know about applets. This will be the foundation of how we discover and communicate with all applets:
- An unmanaged Windows dynamic link library
- Uses the .cpl extension instead of the standard .dll extension
- Exports a single function called CPlApplet
- All applets should be located in the Windows System directory
Comments