Skip to content

Instantly share code, notes, and snippets.

@justaguywhocodes
Created March 21, 2025 13:18
Show Gist options
  • Save justaguywhocodes/430babdf6a1b4949e7e5a3f08d9c5715 to your computer and use it in GitHub Desktop.
Save justaguywhocodes/430babdf6a1b4949e7e5a3f08d9c5715 to your computer and use it in GitHub Desktop.
Here's the DLL code modified to work as C++ (.cpp file). The changes are minimal since the Windows API is C-based, but I'll add some C++ style and error handling:
```cpp
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
STARTUPINFOA si{};
PROCESS_INFORMATION pi{};
// Initialize startup info
si.cb = sizeof(si);
// Create the calculator process
BOOL success = CreateProcessA(
"C:\\Windows\\System32\\calc.exe",
nullptr, // No command line arguments
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
FALSE, // Don't inherit handles
0, // No creation flags
nullptr, // Use parent's environment
nullptr, // Use parent's directory
&si, // Startup info
&pi // Process info
);
if (success)
{
// Clean up handles using RAII-like approach
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
{
// In a real application, you might want to log this
// DWORD error = GetLastError();
return FALSE;
}
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
```
Key C++-specific modifications:
1. Changed `NULL` to `nullptr` for modern C++ style
2. Used uniform initialization syntax with `{}`
3. Added scope blocks `{}` for better variable lifetime management
4. Added basic error handling with return value
To compile as a C++ DLL with g++ (MinGW):
```
g++ -shared -o calc_dll.dll calc_dll.cpp
```
If you want a more C++-style implementation with better error handling, here's an enhanced version:
```cpp
#include <windows.h>
#include <stdexcept>
class ProcessLauncher {
private:
static void CloseHandles(HANDLE hProcess, HANDLE hThread) {
if (hProcess != nullptr) CloseHandle(hProcess);
if (hThread != nullptr) CloseHandle(hThread);
}
public:
static void LaunchCalculator() {
STARTUPINFOA si{};
PROCESS_INFORMATION pi{};
si.cb = sizeof(si);
BOOL success = CreateProcessA(
"C:\\Windows\\System32\\calc.exe",
nullptr,
nullptr,
nullptr,
FALSE,
0,
nullptr,
nullptr,
&si,
&pi
);
if (!success) {
throw std::runtime_error("Failed to launch calculator");
}
CloseHandles(pi.hProcess, pi.hThread);
}
};
extern "C" BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
try {
ProcessLauncher::LaunchCalculator();
}
catch (const std::exception&) {
return FALSE;
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
```
This enhanced version:
1. Uses a class to encapsulate the launching logic
2. Implements proper C++ exception handling
3. Separates handle cleanup into a helper function
4. Uses `extern "C"` to ensure proper linkage for DllMain
Compile with:
```
g++ -shared -o calc_dll.dll calc_dll.cpp -std=c++17
```
Both versions will work as a DLL in a C++ environment. The second version is more "C++-like" but might be overkill for this simple task. Choose based on your specific needs and whether you plan to expand the DLL's functionality later.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment