Skip to content

Instantly share code, notes, and snippets.

@throwaway96
Created November 19, 2023 03:58
Show Gist options
  • Save throwaway96/19b9f3b6c39c6f69217bbacc3b562f08 to your computer and use it in GitHub Desktop.
Save throwaway96/19b9f3b6c39c6f69217bbacc3b562f08 to your computer and use it in GitHub Desktop.
Create hidden window to listen for ports (dis)appearing on Windows
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma warning(push)
#pragma warning(disable:4820)
#include <dbt.h>
#pragma warning(pop)
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <tchar.h>
#include <assert.h>
static HINSTANCE instance_self = NULL;
static ATOM class_atom = INVALID_ATOM;
static HWND window_handle = NULL;
static const LPCTSTR class_name = TEXT("pnClass");
static const LPCTSTR window_name = TEXT("pnWindow");
static bool create_window(void);
static bool cleanup_window(void);
static LRESULT CALLBACK window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static void print_error(const char *func);
static void handle_device_change(PDEV_BROADCAST_PORT lpdbp, bool added);
int main(void) {
instance_self = GetModuleHandle(NULL);
if (!create_window()) {
(void) cleanup_window();
return EXIT_FAILURE;
}
int exit_status = EXIT_SUCCESS;
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, window_handle, 0, 0)) != FALSE) {
if (bRet == -1) {
print_error("GetMessage");
exit_status = EXIT_FAILURE;
break;
}
printf("got message (bRet = %d)\n", bRet);
DispatchMessage(&msg);
}
printf("left message loop (bRet = %d)\n", bRet);
if (!cleanup_window()) {
return EXIT_FAILURE;
}
return exit_status;
}
static bool create_window(void) {
WNDCLASSEX window_class = {
.cbSize = sizeof(WNDCLASSEX),
.style = 0,
.lpfnWndProc = window_proc,
.cbClsExtra = 0,
.cbWndExtra = 0,
.hInstance = instance_self,
.hIcon = NULL,
.hCursor = NULL,
.hbrBackground = NULL,
.lpszMenuName = NULL,
.lpszClassName = class_name,
.hIconSm = NULL,
};
if ((class_atom = RegisterClassEx(&window_class)) == INVALID_ATOM) {
print_error("RegisterClassEx");
return false;
}
if ((window_handle = CreateWindowEx(WS_EX_LEFT, MAKEINTATOM(class_atom), window_name, WS_OVERLAPPED | WS_DISABLED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, instance_self, NULL)) == NULL) {
print_error("CreateWindowEx");
return false;
}
return true;
}
static bool cleanup_window(void) {
if (window_handle != NULL) {
if (DestroyWindow(window_handle) == FALSE) {
print_error("DestroyWindow");
return false;
}
window_handle = NULL;
}
if (class_atom != INVALID_ATOM) {
if (UnregisterClass(MAKEINTATOM(class_atom), instance_self) == FALSE) {
print_error("UnregisterClass");
return false;
}
class_atom = INVALID_ATOM;
}
return true;
}
static LRESULT CALLBACK window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if ((uMsg == WM_DEVICECHANGE) && ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE))) {
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
assert(lpdb != NULL);
if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
assert(lpdb->dbch_size >= sizeof(DEV_BROADCAST_PORT));
handle_device_change((PDEV_BROADCAST_PORT) lParam, (wParam == DBT_DEVICEARRIVAL));
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
static void print_error(const char *func) {
(void) fprintf(stderr, "error: %s: %#08lx\n", func, GetLastError());
return;
}
static void handle_device_change(PDEV_BROADCAST_PORT lpdbp, bool added) {
assert(lpdbp != NULL);
assert(lpdbp->dbcp_size >= sizeof(DEV_BROADCAST_PORT));
LPCTSTR action = added ? TEXT("added") : TEXT("removed");
_tprintf(TEXT("device %s: '%s'\n"), action, lpdbp->dbcp_name);
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment