wil-raii
Enforces RAII patterns for Windows resource management using the Windows Implementation Library.
Install
mkdir -p .claude/skills/wil-raii && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15871" && unzip -o skill.zip -d .claude/skills/wil-raii && rm skill.zipInstalls to .claude/skills/wil-raii
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Windows Implementation Library (WIL) RAII patterns for managing Windows resources. Use when creating, managing, or cleaning up Windows handles like HICON, HWND, HBITMAP, HDC, COM objects, or any GDI resources.Key capabilities
- →Manage HICON resources with `wil::unique_hicon`
- →Manage HWND resources with `wil::unique_hwnd`
- →Manage COM objects with `wil::com_ptr<T>`
- →Handle GDI selections with `wil::SelectObject`
- →Ensure cleanup with `wil::scope_exit`
How it works
The skill provides WIL RAII wrappers and patterns to automatically manage and clean up Windows resources like handles and COM objects.
Inputs & outputs
When to use wil-raii
- →Manage HICON or HWND
- →Clean up COM objects
- →Implement safe GDI resource management
- →Ensure auto-cleanup on exit
About this skill
WIL RAII Resource Management
CRITICAL: NO MANUAL RESOURCE CLEANUP - All Windows resources MUST use RAII wrappers.
goto is prohibited; use wil::scope_exit for cleanup and common exit paths.
WIL Wrapper Reference
| Resource | WIL Wrapper |
|---|---|
| HICON | wil::unique_hicon |
| HWND | wil::unique_hwnd |
| HBITMAP | wil::unique_hbitmap |
| HFONT | wil::unique_any<HFONT, decltype(&::DeleteObject), ::DeleteObject> |
| HBRUSH | wil::unique_any<HBRUSH, decltype(&::DeleteObject), ::DeleteObject> |
| HPEN | wil::unique_any<HPEN, decltype(&::DeleteObject), ::DeleteObject> |
| HDC | wil::unique_hdc |
| Paint | wil::unique_hdc_paint with wil::BeginPaint(hwnd, &ps) |
| COM | wil::com_ptr<T> |
| Cleanup | wil::scope_exit with lambda |
Patterns
Member Variables
class MyWindow
{
wil::unique_hicon _icon;
wil::unique_hwnd _tooltip;
wil::unique_any<HFONT, decltype(&::DeleteObject), ::DeleteObject> _font;
};
Paint Context (auto EndPaint)
PAINTSTRUCT ps;
wil::unique_hdc_paint hdc = wil::BeginPaint(_hWnd, &ps);
FillRect(hdc.get(), &ps.rcPaint, brush);
// Automatic EndPaint on scope exit
GDI Selection (auto restore)
{
auto oldBrush = wil::SelectObject(hdc, _brush.get());
// Drawing...
} // Old brush automatically restored
Direct2D BeginDraw/EndDraw
{
HRESULT hr = S_OK;
{
_d2dContext->BeginDraw();
auto endDraw = wil::scope_exit([&] { hr = _d2dContext->EndDraw(); });
// Drawing operations...
}
if (FAILED(hr)) { /* handle */ }
}
COM Pointers (wil::com_ptr<T>)
Use wil::com_ptr<T> for COM interface lifetimes and prefer single-step copy semantics.
// ✅ Copy (AddRef) in one step
wil::com_ptr<IFileSystem> fs = rawFs;
fs = rawFs;
// ✅ Receive an owning ref via out-param (avoids attach())
wil::com_ptr<IMuffin> muffin;
HRESULT hr = GetMuffin(muffin.put());
Avoid manual ref-counting + attach() on the same pointer:
// ❌ Two-step hazard (can leak a ref if an exception occurs between lines)
rawFs->AddRef();
fs.attach(rawFs);
Required Include
#pragma warning(push)
#pragma warning(disable: 4625 4626 5026 5027 28182)
#include <wil/resource.h>
#pragma warning(pop)
Resource Creation and Access
// Creation
_icon.reset(LoadIcon(...));
_tooltip.reset(CreateWindowExW(...));
// Access raw handle for Win32 APIs
DrawIcon(hdc, x, y, _icon.get());
SendMessageW(_tooltip.get(), WM_SETFONT,
reinterpret_cast<WPARAM>(_font.get()), TRUE);
// Transfer ownership
wil::unique_hbitmap bitmap(CreateCompatibleBitmap(...));
_bitmaps.emplace_back(std::move(bitmap));
// Clear resources
_bitmaps.clear(); // All HBITMAPs automatically deleted
_icon.reset(); // Old icon destroyed, set to nullptr
Destroying Owned Windows (wil::unique_hwnd)
If an HWND is owned by wil::unique_hwnd, destroy via the wrapper (do not call DestroyWindow(_hWnd.get())).
// ✅ Preferred: destroy + clear ownership
_hWnd.reset();
// ✅ Transfer ownership explicitly (rare)
HWND hwnd = _hWnd.release();
DestroyWindow(hwnd);
Menu Cleanup with scope_exit
HMENU menu = CreatePopupMenu();
auto menuCleanup = wil::scope_exit([&] { if (menu) DestroyMenu(menu); });
// Use menu...
// Automatic cleanup on scope exit
Multiple GDI Selections
{
auto oldPen = wil::SelectObject(hdc, _pen.get());
{
auto oldBrush = wil::SelectObject(hdc, _brush.get());
// Draw with pen and brush
} // Brush restored
// Draw with pen only
} // Pen restored
Exception: Transfer-of-Ownership
Cross-thread icon passing is acceptable when properly documented and receiver takes RAII ownership:
// Move unique_hicon across threads
wil::unique_hicon icon = ExtractOnBackgroundThread();
PostToUIThread([icon = std::move(icon)]() {
// UI thread now owns the icon
});
PROHIBITED
goto cleanup patterns are forbidden (prefer early returns + wil::scope_exit).
// ❌ NEVER manual cleanup
DestroyIcon(_icon);
DeleteObject(font);
EndPaint(hWnd, &ps);
// ❌ NEVER destroy an owned HWND via .get()
DestroyWindow(_hWnd.get());
// ❌ NEVER raw handle with manual delete
HFONT font = CreateFontW(...);
// ... use font ...
DeleteObject(font);
// ❌ NEVER vector of raw handles
std::vector<HBITMAP> bitmaps;
for (auto bmp : bitmaps) {
DeleteObject(bmp); // Manual cleanup loop
}
When not to use it
- →When performing manual resource cleanup
- →When using `goto` for cleanup patterns
- →When destroying an owned HWND via `.get()`
Limitations
- →Manual resource cleanup is prohibited
- →`goto` cleanup patterns are forbidden
- →Destroying an owned HWND via `.get()` is prohibited
How it compares
This skill enforces RAII wrappers for all Windows resources, eliminating manual cleanup and `goto` patterns common in traditional Win32 programming.
Compared to similar skills
wil-raii side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| wil-raii (this skill) | 0 | 3mo | No flags | Advanced |
| static-analysis | 5 | 6mo | No flags | Advanced |
| memory-safety-patterns | 4 | 4mo | No flags | Advanced |
| gdb-cli | 0 | 3mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by RedSalamanders
View all by RedSalamanders →You might also like
static-analysis
gmh5225
Expertise in LLVM-based static analysis including dataflow analysis, pointer analysis, taint tracking, and program verification. Use this skill when implementing security scanners, bug finders, code quality tools, or performing program analysis research.
memory-safety-patterns
sickn33
Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.
gdb-cli
Anhvu1107
ALWAYS use this when the request matches GDB CLI: GDB debugging assistant for AI agents - analyze core dumps, debug live processes, investigate crashes and deadlocks with source code correlation
HexCore Binary Analysis
diegosouzapw
Skill para analise de binarios com ferramentas HexCore integradas ao editor
reverse-engineering-tools
gmh5225
Guide for reverse engineering tools and techniques used in game security research. Use this skill when working with debuggers, disassemblers, memory analysis tools, binary analysis, or decompilers for game security research.
ghidra
mitsuhiko
Reverse engineer binaries using Ghidra's headless analyzer. Decompile executables, extract functions, strings, symbols, and analyze call graphs without GUI.