Writing Control Panel Applications

Author

Pavel Yosifovich has 25+ years as Software developer, trainer, consultant, author, and speaker. Co-author of “Windows Internals”. Author of “Windows Kernel Programming”, “Windows 10 System Programming, as well as System and kernel programming courses and “Windows Internals” series.

Control Panel has been part of Windows forever. In recent versions, Microsoft has been moving functionality into Settings, and some classic pages now redirect. But Control Panel is still supported, and many classic applets still exist.

That means you can still write your own Control Panel items. In this post, I’ll show one practical way to do it: a classic Control Panel applet DLL (.cpl) that exports a function called CPlApplet.

Two Ways To Add A Control Panel Item

There are two common approaches:

  1. Register A Normal Executable
    You can write a regular EXE and register it so Control Panel can discover and launch it. This is straightforward and fully documented (search for “registering control panel items” in Microsoft documentation).
  2. Write A CPL DLL (Classic Applet)
    This is the more interesting option. You write a DLL, export a function named CPlApplet, and Control Panel uses a defined message protocol to interact with your applet. That’s what I demonstrate here.

How Control Panel Finds Applets

There are two ways:

  • Drop A .cpl Into System32
    Files in System32 with the .cpl extension are picked up automatically. This is how classic Windows applets are commonly installed. The downside is obvious: writing to System32 requires administrative privileges.
  • Register A CPL Located Elsewhere
    You can store the CPL anywhere and register it via the registry so Control Panel can find it. Again, this is documented by Microsoft.

For a demo, placing the CPL in System32 is the simplest way to validate that everything works.

Running Applets Without Clicking The UI

Windows includes control.exe (in System32). You can use it to launch Control Panel items directly.

You can also use it to test your own CPL file by providing a path. This is useful while you’re developing because you don’t have to rely on Control Panel UI refresh behavior just to run the applet.

Project Setup In Visual Studio

Create a new project using the Visual Studio Desktop wizard and select DLL.

The wizard gives you a standard DLL skeleton (DllMain, headers, and example exports). You don’t need the example exports. What you do need is a correctly named exported function.

The Function You Must Export: CPlApplet

The easiest way to discover the exact signature and required behavior is to look at the header:

  • cpl.h

It contains the function prototype and the message values you need to handle.

The function must be named exactly:

  • CPlApplet

If the name is wrong, Control Panel won’t find it. The function uses WINAPI calling convention (stdcall).

CPlApplet receives:

  • a parent window handle (useful if you show UI)
  • a message indicating what Control Panel wants
  • message-specific parameters

A key point: you’re not “just running a DLL.” Control Panel and your applet follow a small protocol.

Windows master developer badge 1

$1,478

$1182 or $120 X 10 payments

Windows Master Developer

Takes you from a “generic” C programmer to a master Windows programmer in user mode and kernel mode.

The Message Protocol

A typical applet handles these messages:

CPL_INIT

Called early. This is your chance to initialize. Return TRUE to continue or FALSE to indicate failure.

CPL_GETCOUNT

Control Panel asks how many applets you provide. A single DLL can host multiple applets. For this demo, return 1.

CPL_INQUIRE

Control Panel asks for metadata about an applet: name, description, and icon. You return this data through a CPLINFO structure.

The values you provide are typically resource identifiers, not literal strings. That means you need resources in your project.

CPL_DBLCLK

Triggered when the user activates the applet. This is where you do the actual work. For a simple demo, a message box is enough.

There are other messages you can handle, but these are the minimum set to get a working item that appears in Control Panel and reacts when clicked.

Adding Resources (Strings And Icon)

For CPL_INQUIRE, create resources:

  • A String Table with:
    • applet name string
    • applet description string
  • An Icon resource

Then, in CPLINFO, reference these resources by ID.

This is how your applet appears with a proper name, description, and icon in Control Panel.

Building As A .CPL

A CPL file is a DLL with a different extension. You can make your project produce a .cpl directly by changing the output extension in project settings.

That’s convenient because you build and you immediately get something you can copy into place.

$1300

$1040 or $104 X 10 payments

Windows Internals Master

Broadens and deepens your understanding of the inner workings of Windows.

Installing And Verifying

For the simplest test:

  1. Build the project to produce MyApplet.cpl (or any name).
  2. Copy it to C:\Windows\System32 (administrator required).
  3. Open Control Panel and refresh the view.
  4. Your new applet should appear.
  5. Double-click it and verify your CPL_DBLCLK behavior (e.g., a message box).

What Actually Launches A CPL

If you inspect the running processes, you’ll see your CPL is typically launched via rundll32.exe. The infrastructure loads the applet and calls into it through a Control Panel entry point.

This is useful to know for debugging, because you can run the same host process yourself.

Debugging The Applet Properly

Since this is a DLL, you can’t “run it” like a normal EXE.

Two practical options:

  • Use control.exe to launch your CPL for quick testing.
  • For real debugging in Visual Studio, configure the project to start rundll32.exe with the right arguments, so you can hit breakpoints reliably.

A common form looks like:

rundll32.exe shell32.dll,Control_RunDLL C:\Windows\System32\MyApplet.cpl

Once you start the host this way, you can debug the applet normally and watch the calls to CPL_INIT, CPL_INQUIRE, and CPL_DBLCLK as the Control Panel infrastructure interacts with your code.

Why This Matters For TrainSec Students

This is a straightforward example of Windows extensibility that is still present in modern Windows versions.

If you can build a Control Panel applet cleanly, you’re practicing useful fundamentals:

  • building a DLL with a strict exported entry point
  • working with message-driven protocols
  • managing Win32 resources (strings/icons)
  • understanding how Windows hosts and launches components (control.exe, rundll32.exe)
  • debugging non-EXE entry points in a reliable way

Even if you never ship a CPL, the workflow and tooling patterns apply to a lot of Windows internals work. A CPL approach could be used for simple persistence.

Liked the content?

Subscribe to the free TrainSec knowledge library, and get insider access to new content, discounts and additional materials.

Keep Learning with TrainSec

This content is part of the free TrainSec Knowledge Library, where students can deepen their understanding of Windows internals, malware analysis, and reverse engineering. Subscribe for free and continue learning with us:

https://trainsec.net/library

blue depth

About the author

Pavel Yosifovich has 25+ years as Software developer, trainer, consultant, author, and speaker. Co-author of “Windows Internals”. Author of “Windows Kernel Programming”, “Windows 10 System Programming, as well as System and kernel programming courses and “Windows Internals” series.
Even more articles from the free knowledge library
Writing a Simple Key Logger

In this video, Pavel walks through how to implement a basic keylogger in Windows using GetKeyState, handling character normalization (Shift,

Read More