From f64712f2770b2230e9bb7f8b5e9d498404593251 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 17 Jan 2024 17:15:21 -0600 Subject: [PATCH] Always reset the thread desktop before calling DuplicateOutput() Otherwise capture will fail if the thread desktop is different than the current input desktop (ex: UAC secure desktop is active) --- src/platform/windows/display_base.cpp | 15 +++++++++++---- tools/ddprobe.cpp | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index 50f72698..d76a2e0a 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -376,11 +376,15 @@ namespace platf::dxgi { // Check if we can use the Desktop Duplication API on this output for (int x = 0; x < 2; ++x) { dup_t dup; + + // Ensure we can duplicate the current display + syncThreadDesktop(); + status = output1->DuplicateOutput((IUnknown *) device.get(), &dup); if (SUCCEEDED(status)) { return true; } - Sleep(200); + std::this_thread::sleep_for(200ms); } BOOST_LOG(error) << "DuplicateOutput() test failed [0x"sv << util::hex(status).to_string_view() << ']'; @@ -405,9 +409,6 @@ namespace platf::dxgi { FreeLibrary(user32); }); - // Ensure we can duplicate the current display - syncThreadDesktop(); - // Get rectangle of full desktop for absolute mouse coordinates env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); @@ -679,6 +680,9 @@ namespace platf::dxgi { // We try this twice, in case we still get an error on reinitialization for (int x = 0; x < 2; ++x) { + // Ensure we can duplicate the current display + syncThreadDesktop(); + status = output5->DuplicateOutput1((IUnknown *) device.get(), 0, supported_formats.size(), supported_formats.data(), &dup.dup); if (SUCCEEDED(status)) { break; @@ -705,6 +709,9 @@ namespace platf::dxgi { } for (int x = 0; x < 2; ++x) { + // Ensure we can duplicate the current display + syncThreadDesktop(); + status = output1->DuplicateOutput((IUnknown *) device.get(), &dup.dup); if (SUCCEEDED(status)) { break; diff --git a/tools/ddprobe.cpp b/tools/ddprobe.cpp index 423a1f13..68b2da87 100644 --- a/tools/ddprobe.cpp +++ b/tools/ddprobe.cpp @@ -52,6 +52,23 @@ set_gpu_preference(int preference) { return ERROR_SUCCESS; } +void +syncThreadDesktop() { + auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL); + if (!hDesk) { + auto err = GetLastError(); + std::cout << "Failed to Open Input Desktop [0x"sv << util::hex(err).to_string_view() << ']' << std::endl; + return; + } + + if (!SetThreadDesktop(hDesk)) { + auto err = GetLastError(); + std::cout << "Failed to sync desktop to thread [0x"sv << util::hex(err).to_string_view() << ']' << std::endl; + } + + CloseDesktop(hDesk); +} + HRESULT test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) { D3D_FEATURE_LEVEL featureLevels[] { @@ -87,6 +104,9 @@ test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) { return status; } + // Ensure we can duplicate the current display + syncThreadDesktop(); + // Return the result of DuplicateOutput() to Sunshine dxgi::dup_t dup; return output1->DuplicateOutput((IUnknown *) device.get(), &dup);