[feat] add headless compatibility capture and usbmmidd virtual display plugging

This commit is contained in:
dijunkun
2026-09-21 01:10:30 +08:00
parent fb556a763d
commit 6387f2e555
11 changed files with 1510 additions and 59 deletions
@@ -0,0 +1,148 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-09-20
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef CROSSDESK_USBMMIDD_POLICY_H_
#define CROSSDESK_USBMMIDD_POLICY_H_
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <cwctype>
#include <string>
#include <vector>
namespace crossdesk {
// Amyuni "USB Mobile Monitor" indirect display driver (usbmmidd_v2). The
// package ships deviceinstaller64.exe, usbmmIdd.inf/.cat and usbmmIdd.dll. It
// is bundled from apps/desktop/resources/windows/usbmmidd_v2 by the installer
// and the portable archive; a user may also drop it next to the executables.
inline constexpr wchar_t kUsbmmiddHardwareId[] = L"usbmmidd";
// Set when CrossDesk itself installed the driver. The NSIS uninstaller reads
// it (64-bit registry view) and removes the driver only in that case.
inline constexpr wchar_t kUsbmmiddInstallMarkerKey[] = L"SOFTWARE\\CrossDesk";
inline constexpr wchar_t kUsbmmiddInstallMarkerValue[] =
L"UsbmmiddDriverInstalled";
inline constexpr wchar_t kUsbmmiddAdapterDescription[] =
L"USB Mobile Monitor Virtual Display";
#if defined(_WIN64)
inline constexpr wchar_t kUsbmmiddInstallerName[] = L"deviceinstaller64.exe";
#else
inline constexpr wchar_t kUsbmmiddInstallerName[] = L"deviceinstaller.exe";
#endif
inline constexpr wchar_t kUsbmmiddInfName[] = L"usbmmidd.inf";
inline constexpr const wchar_t* kUsbmmiddPackageDirectories[] = {
L"usbmmidd_v2", L"usbmmidd", L"drivers\\usbmmidd_v2"};
// The driver accepts up to four monitors; remote capture needs one.
inline constexpr int kUsbmmiddMaxMonitors = 4;
// Session helper IPC sub-protocol (see session_helper_shared.h for the pipe).
// Plug/unplug run asynchronously in the helper; poll the status command.
inline constexpr char kCrossDeskVirtualDisplayStatusCommand[] =
"virtual-display-status";
inline constexpr char kCrossDeskVirtualDisplayPlugCommandPrefix[] =
"virtual-display-plug:";
inline constexpr char kCrossDeskVirtualDisplayUnplugCommand[] =
"virtual-display-unplug";
struct VirtualDisplayMode {
int width = 0;
int height = 0;
bool operator==(const VirtualDisplayMode& other) const {
return width == other.width && height == other.height;
}
bool operator!=(const VirtualDisplayMode& other) const {
return !(*this == other);
}
};
inline constexpr VirtualDisplayMode kDefaultVirtualDisplayMode{1920, 1080};
inline bool ContainsCaseInsensitive(const std::wstring& haystack,
const std::wstring& needle) {
if (needle.empty()) return true;
if (haystack.size() < needle.size()) return false;
const auto it = std::search(
haystack.begin(), haystack.end(), needle.begin(), needle.end(),
[](wchar_t a, wchar_t b) { return std::towlower(a) == std::towlower(b); });
return it != haystack.end();
}
// EnumDisplayDevices reports the adapter description plus a PnP id such as
// "PCI\VEN_..." or "ROOT\DISPLAY\0000". The IDD adapter carries the hardware
// id in its device id; the description is a second signal for older packages.
inline bool IsUsbmmiddAdapter(const std::wstring& device_string,
const std::wstring& device_id) {
return ContainsCaseInsensitive(device_id, kUsbmmiddHardwareId) ||
ContainsCaseInsensitive(device_string, kUsbmmiddAdapterDescription);
}
// Exact match first; otherwise the largest mode that fits inside the request,
// so a 4K request on a 1080p-only package still yields the best available
// picture; otherwise the smallest mode the driver offers.
inline bool ChooseVirtualDisplayMode(
const std::vector<VirtualDisplayMode>& supported,
VirtualDisplayMode requested, VirtualDisplayMode* chosen) {
if (chosen == nullptr || supported.empty()) return false;
const VirtualDisplayMode* best = nullptr;
const VirtualDisplayMode* smallest = nullptr;
auto area = [](const VirtualDisplayMode& mode) {
return static_cast<long long>(mode.width) * mode.height;
};
for (const auto& mode : supported) {
if (mode.width <= 0 || mode.height <= 0) continue;
if (mode == requested) {
*chosen = mode;
return true;
}
if (mode.width <= requested.width && mode.height <= requested.height &&
(best == nullptr || area(mode) > area(*best))) {
best = &mode;
}
if (smallest == nullptr || area(mode) < area(*smallest)) smallest = &mode;
}
if (best != nullptr) {
*chosen = *best;
return true;
}
if (smallest != nullptr) {
*chosen = *smallest;
return true;
}
return false;
}
// "virtual-display-plug:1920x1080"
inline std::string BuildVirtualDisplayPlugCommand(VirtualDisplayMode mode) {
return std::string(kCrossDeskVirtualDisplayPlugCommandPrefix) +
std::to_string(mode.width) + "x" + std::to_string(mode.height);
}
inline bool ParseVirtualDisplayPlugCommand(const std::string& command,
VirtualDisplayMode* mode) {
if (mode == nullptr) return false;
const std::string prefix(kCrossDeskVirtualDisplayPlugCommandPrefix);
if (command.rfind(prefix, 0) != 0) return false;
const std::string payload = command.substr(prefix.size());
const size_t separator = payload.find('x');
if (separator == std::string::npos || separator == 0 ||
separator + 1 >= payload.size()) {
return false;
}
char* end = nullptr;
const long width = std::strtol(payload.c_str(), &end, 10);
if (end != payload.c_str() + separator) return false;
const long height = std::strtol(payload.c_str() + separator + 1, &end, 10);
if (end == nullptr || *end != '\0') return false;
if (width <= 0 || height <= 0 || width > 16384 || height > 16384) return false;
mode->width = static_cast<int>(width);
mode->height = static_cast<int>(height);
return true;
}
} // namespace crossdesk
#endif // CROSSDESK_USBMMIDD_POLICY_H_
@@ -0,0 +1,384 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-09-20
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#include "usbmmidd_virtual_display.h"
// clang-format off
#include <Windows.h>
#include <initguid.h> // defines GUID_DEVCLASS_DISPLAY in this unit
#include <SetupAPI.h>
#include <devguid.h>
// clang-format on
#include <algorithm>
#include <string>
#include <vector>
#include "rd_log.h"
namespace crossdesk {
namespace {
constexpr DWORD kInstallerPollIntervalMs = 250;
constexpr DWORD kDriverInstallTimeoutMs = 90 * 1000;
constexpr DWORD kInstallerCommandTimeoutMs = 20 * 1000;
std::string Narrow(const std::wstring& value) {
if (value.empty()) return {};
const int size = WideCharToMultiByte(CP_UTF8, 0, value.data(),
static_cast<int>(value.size()), nullptr,
0, nullptr, nullptr);
std::string result(static_cast<size_t>((std::max)(size, 0)), '\0');
if (size > 0) {
WideCharToMultiByte(CP_UTF8, 0, value.data(),
static_cast<int>(value.size()), result.data(), size,
nullptr, nullptr);
}
return result;
}
void SetError(std::string* error, const std::string& message) {
if (error != nullptr) *error = message;
}
std::filesystem::path CurrentExecutableDirectory() {
wchar_t module_path[MAX_PATH] = {0};
const DWORD length = GetModuleFileNameW(nullptr, module_path, MAX_PATH);
if (length == 0 || length >= MAX_PATH) return {};
return std::filesystem::path(module_path).parent_path();
}
struct UsbmmiddAdapter {
std::wstring device_name; // \\.\DISPLAYn
bool attached_to_desktop = false;
};
std::vector<UsbmmiddAdapter> EnumerateUsbmmiddAdapters() {
std::vector<UsbmmiddAdapter> adapters;
for (DWORD index = 0;; ++index) {
DISPLAY_DEVICEW device{sizeof(device)};
if (!EnumDisplayDevicesW(nullptr, index, &device, 0)) break;
if (!IsUsbmmiddAdapter(device.DeviceString, device.DeviceID)) continue;
UsbmmiddAdapter adapter;
adapter.device_name = device.DeviceName;
adapter.attached_to_desktop =
(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0;
adapters.push_back(std::move(adapter));
}
return adapters;
}
// Runs "<installer> <arguments>" hidden with the package folder as the
// working directory (the installer resolves usbmmIdd.dll relative to it).
bool RunUsbmmiddInstaller(const UsbmmiddPackage& package,
const std::wstring& arguments, DWORD timeout_ms,
std::string* error) {
if (!package.Available()) {
SetError(error, "usbmmidd_package_missing");
return false;
}
std::wstring command_line =
L"\"" + package.installer.wstring() + L"\" " + arguments;
STARTUPINFOW startup{};
startup.cb = sizeof(startup);
PROCESS_INFORMATION process{};
const std::wstring working_directory = package.directory.wstring();
if (!CreateProcessW(package.installer.c_str(), command_line.data(), nullptr,
nullptr, FALSE, CREATE_NO_WINDOW, nullptr,
working_directory.c_str(), &startup, &process)) {
const DWORD code = GetLastError();
// 740 (ERROR_ELEVATION_REQUIRED) is the non-elevated GUI fallback path.
SetError(error, "usbmmidd_installer_launch_failed:" + std::to_string(code));
return false;
}
CloseHandle(process.hThread);
const DWORD wait = WaitForSingleObject(process.hProcess, timeout_ms);
DWORD exit_code = 0;
if (wait != WAIT_OBJECT_0) {
TerminateProcess(process.hProcess, 1);
CloseHandle(process.hProcess);
SetError(error, wait == WAIT_TIMEOUT ? "usbmmidd_installer_timeout"
: "usbmmidd_installer_wait_failed");
return false;
}
GetExitCodeProcess(process.hProcess, &exit_code);
CloseHandle(process.hProcess);
if (exit_code != 0) {
SetError(error, "usbmmidd_installer_exit:" + std::to_string(exit_code));
return false;
}
return true;
}
// Waits until |predicate| holds or the deadline passes.
template <typename Predicate>
bool WaitUntil(DWORD timeout_ms, Predicate predicate) {
const ULONGLONG deadline = GetTickCount64() + timeout_ms;
while (true) {
if (predicate()) return true;
const ULONGLONG now = GetTickCount64();
if (now >= deadline) return false;
Sleep(static_cast<DWORD>(
(std::min)(static_cast<ULONGLONG>(kInstallerPollIntervalMs),
deadline - now)));
}
}
// The uninstaller removes the driver only when CrossDesk installed it, so a
// driver the user set up for other software is left alone. The helper runs as
// SYSTEM and the in-process path is elevated, so HKLM is writable here; a
// failure only costs a stale device node after uninstall.
void MarkUsbmmiddDriverInstalledByCrossDesk() {
HKEY key = nullptr;
const LONG open = RegCreateKeyExW(HKEY_LOCAL_MACHINE, kUsbmmiddInstallMarkerKey,
0, nullptr, 0, KEY_SET_VALUE, nullptr, &key,
nullptr);
if (open != ERROR_SUCCESS) {
LOG_WARN("usbmmidd: failed to record the driver install marker, error={}",
open);
return;
}
const DWORD value = 1;
const LONG set = RegSetValueExW(key, kUsbmmiddInstallMarkerValue, 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&value),
sizeof(value));
RegCloseKey(key);
if (set != ERROR_SUCCESS) {
LOG_WARN("usbmmidd: failed to record the driver install marker, error={}",
set);
}
}
bool DeviceHasUsbmmiddHardwareId(HDEVINFO device_info,
SP_DEVINFO_DATA* device_data) {
DWORD required = 0;
SetupDiGetDeviceRegistryPropertyW(device_info, device_data, SPDRP_HARDWAREID,
nullptr, nullptr, 0, &required);
if (required == 0) return false;
std::vector<wchar_t> buffer(required / sizeof(wchar_t) + 2, L'\0');
if (!SetupDiGetDeviceRegistryPropertyW(
device_info, device_data, SPDRP_HARDWAREID, nullptr,
reinterpret_cast<BYTE*>(buffer.data()),
static_cast<DWORD>(buffer.size() * sizeof(wchar_t)), nullptr)) {
return false;
}
// REG_MULTI_SZ: hardware ids separated by NUL, terminated by a double NUL.
for (const wchar_t* id = buffer.data(); *id != L'\0'; id += wcslen(id) + 1) {
if (ContainsCaseInsensitive(id, kUsbmmiddHardwareId)) return true;
}
return false;
}
std::vector<VirtualDisplayMode> EnumerateModes(const std::wstring& device) {
std::vector<VirtualDisplayMode> modes;
for (DWORD index = 0;; ++index) {
DEVMODEW mode{};
mode.dmSize = sizeof(mode);
if (!EnumDisplaySettingsExW(device.c_str(), index, &mode, 0)) break;
if (mode.dmBitsPerPel != 32) continue;
const VirtualDisplayMode candidate{static_cast<int>(mode.dmPelsWidth),
static_cast<int>(mode.dmPelsHeight)};
if (std::find(modes.begin(), modes.end(), candidate) == modes.end()) {
modes.push_back(candidate);
}
}
return modes;
}
} // namespace
UsbmmiddPackage LocateUsbmmiddPackage() {
UsbmmiddPackage package;
const std::filesystem::path base = CurrentExecutableDirectory();
if (base.empty()) return package;
std::error_code ignored;
for (const wchar_t* relative : kUsbmmiddPackageDirectories) {
const std::filesystem::path directory = base / relative;
const std::filesystem::path installer = directory / kUsbmmiddInstallerName;
if (!std::filesystem::is_regular_file(installer, ignored)) continue;
package.directory = directory;
package.installer = installer;
const std::filesystem::path inf = directory / kUsbmmiddInfName;
if (std::filesystem::is_regular_file(inf, ignored)) package.inf = inf;
break;
}
return package;
}
int CountUsbmmiddMonitors() {
int count = 0;
for (const auto& adapter : EnumerateUsbmmiddAdapters()) {
if (adapter.attached_to_desktop) ++count;
}
return count;
}
bool IsUsbmmiddDriverInstalled() {
const HDEVINFO device_info = SetupDiGetClassDevsW(
&GUID_DEVCLASS_DISPLAY, nullptr, nullptr, DIGCF_PRESENT);
if (device_info == INVALID_HANDLE_VALUE) {
// Fall back to the adapter list; it misses an installed-but-idle driver.
return !EnumerateUsbmmiddAdapters().empty();
}
bool installed = false;
SP_DEVINFO_DATA device_data{};
device_data.cbSize = sizeof(device_data);
for (DWORD index = 0;
!installed && SetupDiEnumDeviceInfo(device_info, index, &device_data);
++index) {
installed = DeviceHasUsbmmiddHardwareId(device_info, &device_data);
}
SetupDiDestroyDeviceInfoList(device_info);
return installed || !EnumerateUsbmmiddAdapters().empty();
}
UsbmmiddStatus QueryUsbmmiddStatus() {
UsbmmiddStatus status;
const UsbmmiddPackage package = LocateUsbmmiddPackage();
status.package_available = package.Available();
status.package_directory = Narrow(package.directory.wstring());
status.driver_installed = IsUsbmmiddDriverInstalled();
status.plugged_monitors = CountUsbmmiddMonitors();
return status;
}
bool InstallUsbmmiddDriver(const UsbmmiddPackage& package, std::string* error) {
if (IsUsbmmiddDriverInstalled()) return true;
if (package.inf.empty()) {
SetError(error, "usbmmidd_inf_missing");
return false;
}
LOG_INFO("usbmmidd: installing driver from '{}'",
Narrow(package.directory.wstring()));
const std::wstring arguments = L"install \"" + package.inf.wstring() +
L"\" " + kUsbmmiddHardwareId;
if (!RunUsbmmiddInstaller(package, arguments, kDriverInstallTimeoutMs,
error)) {
return false;
}
if (!WaitUntil(5000, IsUsbmmiddDriverInstalled)) {
SetError(error, "usbmmidd_driver_not_present_after_install");
return false;
}
MarkUsbmmiddDriverInstalledByCrossDesk();
return true;
}
bool PlugUsbmmiddMonitor(const UsbmmiddPackage& package, DWORD timeout_ms,
std::string* error) {
const int before = CountUsbmmiddMonitors();
if (before >= kUsbmmiddMaxMonitors) {
SetError(error, "usbmmidd_monitor_limit");
return false;
}
if (!RunUsbmmiddInstaller(package, L"enableidd 1",
kInstallerCommandTimeoutMs, error)) {
return false;
}
if (!WaitUntil(timeout_ms,
[before] { return CountUsbmmiddMonitors() > before; })) {
SetError(error, "usbmmidd_monitor_not_attached");
return false;
}
return true;
}
bool UnplugUsbmmiddMonitor(const UsbmmiddPackage& package, DWORD timeout_ms,
std::string* error) {
const int before = CountUsbmmiddMonitors();
if (before == 0) return true;
if (!RunUsbmmiddInstaller(package, L"enableidd 0",
kInstallerCommandTimeoutMs, error)) {
return false;
}
if (!WaitUntil(timeout_ms,
[before] { return CountUsbmmiddMonitors() < before; })) {
SetError(error, "usbmmidd_monitor_still_attached");
return false;
}
return true;
}
bool ApplyUsbmmiddDisplayMode(VirtualDisplayMode requested,
std::string* error) {
std::wstring device;
for (const auto& adapter : EnumerateUsbmmiddAdapters()) {
if (adapter.attached_to_desktop) {
device = adapter.device_name;
break;
}
}
if (device.empty()) {
SetError(error, "usbmmidd_monitor_not_attached");
return false;
}
VirtualDisplayMode chosen;
if (!ChooseVirtualDisplayMode(EnumerateModes(device), requested, &chosen)) {
SetError(error, "usbmmidd_no_display_modes");
return false;
}
DEVMODEW current{};
current.dmSize = sizeof(current);
if (EnumDisplaySettingsExW(device.c_str(), ENUM_CURRENT_SETTINGS, &current,
0) &&
static_cast<int>(current.dmPelsWidth) == chosen.width &&
static_cast<int>(current.dmPelsHeight) == chosen.height) {
return true;
}
DEVMODEW mode{};
mode.dmSize = sizeof(mode);
mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
mode.dmPelsWidth = static_cast<DWORD>(chosen.width);
mode.dmPelsHeight = static_cast<DWORD>(chosen.height);
mode.dmBitsPerPel = 32;
const LONG result = ChangeDisplaySettingsExW(device.c_str(), &mode, nullptr,
CDS_UPDATEREGISTRY, nullptr);
if (result != DISP_CHANGE_SUCCESSFUL) {
SetError(error, "usbmmidd_mode_change_failed:" + std::to_string(result));
return false;
}
LOG_INFO("usbmmidd: display '{}' set to {}x{} (requested {}x{})",
Narrow(device), chosen.width, chosen.height, requested.width,
requested.height);
return true;
}
bool ProvisionUsbmmiddDisplay(VirtualDisplayMode mode, int* plugged,
std::string* error) {
if (plugged != nullptr) *plugged = 0;
const UsbmmiddPackage package = LocateUsbmmiddPackage();
if (!package.Available()) {
SetError(error, "usbmmidd_package_missing");
return false;
}
if (!InstallUsbmmiddDriver(package, error)) return false;
if (CountUsbmmiddMonitors() == 0) {
if (!PlugUsbmmiddMonitor(package, 10 * 1000, error)) return false;
if (plugged != nullptr) *plugged = 1;
}
std::string mode_error;
if (!ApplyUsbmmiddDisplayMode(mode, &mode_error)) {
LOG_WARN("usbmmidd: keeping the driver default mode, error={}", mode_error);
}
return true;
}
bool ReleaseUsbmmiddDisplays(int count, std::string* error) {
const int to_unplug = (std::min)(count, CountUsbmmiddMonitors());
if (to_unplug <= 0) return true;
const UsbmmiddPackage package = LocateUsbmmiddPackage();
if (!package.Available()) {
SetError(error, "usbmmidd_package_missing");
return false;
}
for (int index = 0; index < to_unplug; ++index) {
if (!UnplugUsbmmiddMonitor(package, 10 * 1000, error)) return false;
}
return true;
}
} // namespace crossdesk
@@ -0,0 +1,69 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-09-20
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef CROSSDESK_USBMMIDD_VIRTUAL_DISPLAY_H_
#define CROSSDESK_USBMMIDD_VIRTUAL_DISPLAY_H_
#include <Windows.h>
#include <filesystem>
#include <string>
#include "usbmmidd_policy.h"
namespace crossdesk {
// Plug/unplug talks to the driver through Amyuni's installer and needs
// administrator rights inside the interactive session. The session helper
// (SYSTEM, console session) is the intended caller; the GUI only calls these
// directly when it is elevated and no helper is reachable.
struct UsbmmiddPackage {
std::filesystem::path directory;
std::filesystem::path installer;
std::filesystem::path inf; // empty when only the installer is present
bool Available() const { return !installer.empty(); }
};
// Looks next to the running executable (usbmmidd_v2\, usbmmidd\,
// drivers\usbmmidd_v2\). Both the GUI and the helper live in the same folder.
UsbmmiddPackage LocateUsbmmiddPackage();
struct UsbmmiddStatus {
bool package_available = false;
bool driver_installed = false;
int plugged_monitors = 0;
std::string package_directory;
};
UsbmmiddStatus QueryUsbmmiddStatus();
// Adapters attached to the desktop, i.e. monitors currently plugged in.
int CountUsbmmiddMonitors();
// Root-enumerated device node present, plugged or not.
bool IsUsbmmiddDriverInstalled();
// Each step is idempotent so a retry after a partial failure converges.
bool InstallUsbmmiddDriver(const UsbmmiddPackage& package, std::string* error);
bool PlugUsbmmiddMonitor(const UsbmmiddPackage& package, DWORD timeout_ms,
std::string* error);
bool UnplugUsbmmiddMonitor(const UsbmmiddPackage& package, DWORD timeout_ms,
std::string* error);
// Applies the closest supported mode to the first plugged usbmmidd monitor.
bool ApplyUsbmmiddDisplayMode(VirtualDisplayMode requested, std::string* error);
// Installs the driver on first use, plugs one monitor when none is attached
// and applies |mode|. A mode failure is logged but keeps the display.
// |plugged| receives how many monitors this call plugged (0 when an existing
// usbmmidd monitor was reused) so the caller can release exactly those.
bool ProvisionUsbmmiddDisplay(VirtualDisplayMode mode, int* plugged,
std::string* error);
// Unplugs up to |count| usbmmidd monitors, never more than are attached. A
// monitor plugged by the user or another program is left alone.
bool ReleaseUsbmmiddDisplays(int count, std::string* error);
} // namespace crossdesk
#endif // CROSSDESK_USBMMIDD_VIRTUAL_DISPLAY_H_
@@ -0,0 +1,263 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-09-20
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#include "virtual_display_provisioner.h"
#include <algorithm>
#include <functional>
#include <nlohmann/json.hpp>
#include <string>
#include <vector>
#include "display_presence.h"
#include "named_pipe_deadline.h"
#include "rd_log.h"
#include "session_helper_shared.h"
#include "usbmmidd_virtual_display.h"
namespace crossdesk {
namespace {
using Json = nlohmann::json;
constexpr DWORD kHelperStatusTimeoutMs = 500;
constexpr DWORD kHelperCommandTimeoutMs = 2000;
constexpr DWORD kHelperPollIntervalMs = 250;
constexpr DWORD kPlugTimeoutMs = 20 * 1000;
constexpr DWORD kInstallAndPlugTimeoutMs = 120 * 1000;
constexpr DWORD kUnplugTimeoutMs = 10 * 1000;
constexpr DWORD kPresenceSettleTimeoutMs = 5 * 1000;
struct HelperVirtualDisplayStatus {
bool ok = false;
bool package_available = false;
bool driver_installed = false;
int plugged_monitors = 0;
bool busy = false;
std::string last_error;
std::string error; // transport or helper-reported error
};
std::wstring OwnSessionHelperPipeName() {
DWORD session_id = 0xFFFFFFFF;
if (!ProcessIdToSessionId(GetCurrentProcessId(), &session_id)) return {};
return GetCrossDeskSessionHelperPipeName(session_id);
}
bool QueryHelper(const std::wstring& pipe, const std::string& command,
DWORD timeout_ms, Json* json, std::string* error) {
std::vector<uint8_t> response;
DWORD code = 0;
if (!QueryNamedPipeWithDeadline(pipe, command, timeout_ms, &response, error,
&code)) {
*error += ":" + std::to_string(code);
return false;
}
*json = Json::parse(response.begin(), response.end(), nullptr, false);
if (json->is_discarded() || !json->is_object()) {
*error = "invalid_helper_json";
return false;
}
if (!json->value("ok", false)) {
*error = json->value("error", std::string("helper_error"));
return false;
}
return true;
}
HelperVirtualDisplayStatus QueryHelperStatus(const std::wstring& pipe) {
HelperVirtualDisplayStatus status;
Json json;
if (!QueryHelper(pipe, kCrossDeskVirtualDisplayStatusCommand,
kHelperStatusTimeoutMs, &json, &status.error)) {
return status;
}
status.ok = true;
status.package_available = json.value("package_available", false);
status.driver_installed = json.value("driver_installed", false);
status.plugged_monitors = json.value("plugged_monitors", 0);
status.busy = json.value("busy", false);
status.last_error = json.value("last_error", std::string());
return status;
}
// Waits for the helper job to finish; returns false with the job's error.
// |cancelled| stops the wait early (the helper job itself keeps running).
bool WaitForHelperJob(const std::wstring& pipe, DWORD timeout_ms,
const std::function<bool()>& cancelled,
HelperVirtualDisplayStatus* final_status,
std::string* error) {
const ULONGLONG deadline = GetTickCount64() + timeout_ms;
while (true) {
*final_status = QueryHelperStatus(pipe);
if (!final_status->ok) {
*error = final_status->error;
return false;
}
if (!final_status->busy) {
if (!final_status->last_error.empty()) {
*error = final_status->last_error;
return false;
}
return true;
}
if (cancelled()) {
*error = "cancelled";
return false;
}
if (GetTickCount64() >= deadline) {
*error = "helper_job_timeout";
return false;
}
Sleep(kHelperPollIntervalMs);
}
}
bool WaitForDisplayPresence(DWORD timeout_ms,
const std::function<bool()>& cancelled) {
const ULONGLONG deadline = GetTickCount64() + timeout_ms;
while (true) {
if (ClassifyDisplayPresence(ProbeDisplayPresence()) ==
DisplayPresence::present) {
return true;
}
if (cancelled() || GetTickCount64() >= deadline) return false;
Sleep(kHelperPollIntervalMs);
}
}
} // namespace
bool VirtualDisplayProvisioner::AcquireViaHelper(VirtualDisplayMode mode,
std::string* error,
bool* helper_reachable) {
*helper_reachable = false;
const std::wstring pipe = OwnSessionHelperPipeName();
if (pipe.empty()) {
*error = "session_id_unavailable";
return false;
}
HelperVirtualDisplayStatus status = QueryHelperStatus(pipe);
if (!status.ok) {
*error = status.error;
return false;
}
*helper_reachable = true;
if (!status.package_available) {
*error = "usbmmidd_package_missing";
return false;
}
const auto cancelled = [this] { return Cancelled(); };
if (status.busy) {
// A previous unplug may still be running; let it finish first.
if (!WaitForHelperJob(pipe, kUnplugTimeoutMs, cancelled, &status, error))
return false;
}
Json json;
if (!QueryHelper(pipe, BuildVirtualDisplayPlugCommand(mode),
kHelperCommandTimeoutMs, &json, error)) {
return false;
}
const DWORD timeout =
status.driver_installed ? kPlugTimeoutMs : kInstallAndPlugTimeoutMs;
if (!WaitForHelperJob(pipe, timeout, cancelled, &status, error)) {
// The helper finishes the plug on its own; Release() must undo it.
if (*error == "cancelled") pending_helper_release_ = true;
return false;
}
if (status.plugged_monitors <= 0) {
*error = "usbmmidd_monitor_not_attached";
return false;
}
return true;
}
bool VirtualDisplayProvisioner::AcquireLocally(VirtualDisplayMode mode,
std::string* error) {
if (!LocateUsbmmiddPackage().Available()) {
*error = "usbmmidd_package_missing";
return false;
}
return ProvisionUsbmmiddDisplay(mode, &plugged_locally_, error);
}
bool VirtualDisplayProvisioner::Acquire(VirtualDisplayMode mode,
std::string* error) {
std::string local_error;
if (error == nullptr) error = &local_error;
if (active_.load(std::memory_order_relaxed)) return true;
cancel_.store(false, std::memory_order_relaxed);
bool helper_reachable = false;
const ULONGLONG started = GetTickCount64();
bool ok = AcquireViaHelper(mode, error, &helper_reachable);
if (ok) {
via_helper_ = true;
} else if (!helper_reachable && *error != "cancelled") {
LOG_INFO("Virtual display: session helper unreachable ({}), trying "
"in-process provisioning",
*error);
ok = AcquireLocally(mode, error);
via_helper_ = false;
}
if (!ok) {
LOG_WARN("Virtual display: provisioning failed after {} ms, error={}",
GetTickCount64() - started, *error);
return false;
}
// The desktop moves onto the new target asynchronously; DXGI needs it.
if (!WaitForDisplayPresence(kPresenceSettleTimeoutMs,
[this] { return Cancelled(); })) {
LOG_WARN("Virtual display: monitor plugged but no display target became "
"available within {} ms",
kPresenceSettleTimeoutMs);
}
active_.store(true, std::memory_order_relaxed);
LOG_INFO("Virtual display: usbmmidd monitor ready via {} in {} ms "
"(requested {}x{})",
via_helper_ ? "session helper" : "this process",
GetTickCount64() - started, mode.width, mode.height);
return true;
}
void VirtualDisplayProvisioner::Release() {
const bool was_active = active_.exchange(false, std::memory_order_relaxed);
// via_helper_ is only set by a completed helper plug; a cancelled one is
// tracked by pending_helper_release_ instead.
const bool release_helper =
(via_helper_ && was_active) || pending_helper_release_;
const bool release_local = !release_helper && plugged_locally_ > 0;
if (!release_helper && !release_local) return;
std::string error;
bool ok = false;
if (release_helper) {
const std::wstring pipe = OwnSessionHelperPipeName();
Json json;
HelperVirtualDisplayStatus status;
ok = !pipe.empty() &&
QueryHelper(pipe, kCrossDeskVirtualDisplayUnplugCommand,
kHelperCommandTimeoutMs, &json, &error);
// Wait for the unplug so a Start() right after this Stop() probes the
// desktop without the outgoing monitor. A plug still running in the helper
// queues the unplug behind itself; the next Acquire() waits for that job.
if (ok && !json.value("queued", false)) {
ok = WaitForHelperJob(pipe, kUnplugTimeoutMs, [] { return false; },
&status, &error);
}
if (ok) pending_helper_release_ = false;
} else {
ok = ReleaseUsbmmiddDisplays(plugged_locally_, &error);
if (ok) plugged_locally_ = 0;
}
if (ok) {
LOG_INFO("Virtual display: usbmmidd monitor released");
} else {
LOG_WARN("Virtual display: release failed, error={}", error);
}
}
} // namespace crossdesk
@@ -0,0 +1,63 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-09-20
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef CROSSDESK_VIRTUAL_DISPLAY_PROVISIONER_H_
#define CROSSDESK_VIRTUAL_DISPLAY_PROVISIONER_H_
#include <Windows.h>
#include <atomic>
#include <string>
#include "usbmmidd_policy.h"
namespace crossdesk {
// Session-scoped usbmmidd virtual display for a host without any monitor.
// Acquire() asks the session helper (SYSTEM in the console session) to
// install/plug the driver; without a reachable helper an elevated GUI does it
// itself. Release() unplugs only what this object plugged.
class VirtualDisplayProvisioner {
public:
VirtualDisplayProvisioner() = default;
~VirtualDisplayProvisioner() { Release(); }
VirtualDisplayProvisioner(const VirtualDisplayProvisioner&) = delete;
VirtualDisplayProvisioner& operator=(const VirtualDisplayProvisioner&) =
delete;
bool Acquire(VirtualDisplayMode mode, std::string* error);
void Release();
bool active() const { return active_.load(std::memory_order_relaxed); }
// True when Release() has something to undo. Read on the owner's thread
// after the provisioning worker has been joined.
bool NeedsRelease() const {
return active() || pending_helper_release_ || plugged_locally_ > 0;
}
// Makes a blocking Acquire() return early with "cancelled" at its next poll
// (helper install/plug can take up to two minutes). Cleared by Acquire().
void RequestCancel() { cancel_.store(true, std::memory_order_relaxed); }
private:
// |helper_reachable| tells the caller whether a local fallback makes sense.
bool AcquireViaHelper(VirtualDisplayMode mode, std::string* error,
bool* helper_reachable);
bool AcquireLocally(VirtualDisplayMode mode, std::string* error);
bool Cancelled() const { return cancel_.load(std::memory_order_relaxed); }
// Acquire/Release run on the owner's provisioning worker; active() and
// RequestCancel() are used from other threads.
std::atomic<bool> active_{false};
std::atomic<bool> cancel_{false};
bool via_helper_ = false;
// A cancelled helper plug still completes in the helper; Release() undoes it.
bool pending_helper_release_ = false;
// Monitors plugged by this process (helper-plugged ones are tracked there).
int plugged_locally_ = 0;
};
} // namespace crossdesk
#endif // CROSSDESK_VIRTUAL_DISPLAY_PROVISIONER_H_