13 #include <config_folders.h>
15 #if !defined WIN32_LEAN_AND_MEAN
16 # define WIN32_LEAN_AND_MEAN
24 #include <string_view>
26 #include <osl/file.hxx>
27 #include <rtl/bootstrap.hxx>
28 #include <rtl/ustrbuf.hxx>
37 bool GetKeyValue(
const WCHAR* keyLocation,
const WCHAR* keyName, OUString& destString,
int type)
46 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
47 if (result != ERROR_SUCCESS)
57 dwcbData =
sizeof(dValue);
58 result = RegQueryValueExW(key, keyName,
nullptr, &resultType,
59 reinterpret_cast<LPBYTE>(&dValue), &dwcbData);
60 if (result == ERROR_SUCCESS && resultType == REG_DWORD)
62 dValue = dValue / 1024 / 1024;
63 destString += OUString::number(int32_t(dValue));
74 WCHAR wCharValue[1024];
75 dwcbData =
sizeof(wCharValue);
77 result = RegQueryValueExW(key, keyName,
nullptr, &resultType,
78 reinterpret_cast<LPBYTE>(wCharValue), &dwcbData);
79 if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ)
84 DWORD strLen = dwcbData/
sizeof(wCharValue[0]);
85 for (DWORD
i = 0;
i < strLen;
i++)
87 if (wCharValue[
i] ==
'\0')
89 if (
i < strLen - 1 && wCharValue[
i + 1] ==
'\0')
102 wCharValue[strLen-1] =
'\0';
105 destString = OUString(o3tl::toU(wCharValue));
123 uint32_t ParseIDFromDeviceID(
const OUString &key,
const char *
prefix,
int length)
125 OUString
id = key.toAsciiUpperCase();
126 OUString aPrefix = OUString::fromUtf8(prefix);
127 int32_t start =
id.indexOf(aPrefix);
130 id =
id.copy(start + aPrefix.getLength(), length);
132 return id.toUInt32(16);
141 template<
typename T>
void appendIntegerWithPadding(OUString& rString, T
value, sal_uInt32 nChars)
144 OUString aValue = OUString::number(value, 16);
145 sal_Int32
nLength = aValue.getLength();
146 sal_uInt32 nPadLength = nChars - nLength;
149 for (sal_uInt32
i = 0;
i < nPadLength; ++
i)
153 rString += aBuffer.makeStringAndClear() + aValue;
156 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
172 OUString url(
"$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER);
173 rtl::Bootstrap::expandMacros(url);
175 return url +
"/opengl/opengl_denylist_windows.xml";
186 OUString getCacheFolder()
188 OUString url(
"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"bootstrap")
":UserInstallation}/cache/");
189 rtl::Bootstrap::expandMacros(url);
191 osl::Directory::create(url);
196 void writeToLog(
SvStream& rStrm,
const char* pKey, std::u16string_view rVal)
221 OUString aCacheFolder = getCacheFolder();
223 OUString aCacheFile(aCacheFolder +
"/opengl_device.log");
224 SvFileStream aOpenGLLogFile(aCacheFile, StreamMode::WRITE|StreamMode::TRUNC);
228 writeToLog(aOpenGLLogFile,
"DeviceID",
maDeviceID);
232 writeToLog(aOpenGLLogFile,
"DeviceKey",
maDeviceKey);
241 SAL_WARN(
"vcl.opengl",
"all OpenGL blocked for RDP sessions");
250 DISPLAY_DEVICEW displayDevice;
251 displayDevice.cb =
sizeof(displayDevice);
255 while (EnumDisplayDevicesW(
nullptr, deviceIndex, &displayDevice, 0))
257 if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
266 if (wcsnlen(displayDevice.DeviceKey,
SAL_N_ELEMENTS(displayDevice.DeviceKey))
270 SAL_WARN(
"vcl.opengl",
"string not null terminated");
279 SAL_WARN(
"vcl.opengl",
"incorrect DeviceKey");
286 maDeviceID = o3tl::toU(displayDevice.DeviceID);
295 SAL_WARN(
"vcl.opengl",
"RDP => blocked");
300 HDEVINFO devinfo = SetupDiGetClassDevsW(
nullptr, o3tl::toW(
maDeviceID.getStr()),
nullptr,
301 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
303 if (devinfo != INVALID_HANDLE_VALUE)
309 SP_DEVINFO_DATA devinfoData;
310 DWORD memberIndex = 0;
312 devinfoData.cbSize =
sizeof(devinfoData);
314 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData))
317 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
321 reinterpret_cast<PBYTE>(value),
325 OUString driverKey(OUStringLiteral(
u"System\\CurrentControlSet\\Control\\Class\\") + o3tl::toU(value));
326 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, o3tl::toW(driverKey.getStr()), 0, KEY_QUERY_VALUE, &key);
327 if (result == ERROR_SUCCESS)
330 dwcbData =
sizeof(value);
331 result = RegQueryValueExW(key, L
"DriverVersion",
nullptr,
nullptr,
332 reinterpret_cast<LPBYTE>(value), &dwcbData);
333 if (result == ERROR_SUCCESS)
342 dwcbData =
sizeof(value);
343 result = RegQueryValueExW(key, L
"DriverDate",
nullptr,
nullptr,
344 reinterpret_cast<LPBYTE>(value), &dwcbData);
345 if (result == ERROR_SUCCESS)
360 SetupDiDestroyDeviceInfoList(devinfo);
364 SAL_WARN(
"vcl.opengl",
"invalid handle value");
374 CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
375 HRESULT hresult = CLSIDFromString(L
"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
376 &GUID_DISPLAY_DEVICE_ARRIVAL);
377 if (hresult == NOERROR)
379 devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL,
381 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
383 if (devinfo != INVALID_HANDLE_VALUE)
389 SP_DEVINFO_DATA devinfoData;
390 DWORD memberIndex = 0;
391 devinfoData.cbSize =
sizeof(devinfoData);
393 OUString aAdapterDriver2;
395 OUString aDriverVersion2;
396 OUString aDriverDate2;
397 uint32_t adapterVendorID2;
398 uint32_t adapterDeviceID2;
401 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData))
404 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
408 reinterpret_cast<PBYTE>(value),
412 OUString driverKey2(OUStringLiteral(
u"System\\CurrentControlSet\\Control\\Class\\") + o3tl::toU(value));
413 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, o3tl::toW(driverKey2.getStr()), 0, KEY_QUERY_VALUE, &key);
414 if (result == ERROR_SUCCESS)
416 dwcbData =
sizeof(value);
417 result = RegQueryValueExW(key, L
"MatchingDeviceId",
nullptr,
418 nullptr, reinterpret_cast<LPBYTE>(value), &dwcbData);
419 if (result != ERROR_SUCCESS)
423 aDeviceID2 = o3tl::toU(value);
424 OUString aAdapterVendorID2String;
425 OUString aAdapterDeviceID2String;
426 adapterVendorID2 = ParseIDFromDeviceID(aDeviceID2,
"VEN_", 4);
427 appendIntegerWithPadding(aAdapterVendorID2String, adapterVendorID2, 4);
428 adapterDeviceID2 = ParseIDFromDeviceID(aDeviceID2,
"&DEV_", 4);
429 appendIntegerWithPadding(aAdapterDeviceID2String, adapterDeviceID2, 4);
439 if (!GetKeyValue(o3tl::toW(driverKey2.getStr()), L
"InstalledDisplayDrivers",
440 aAdapterDriver2, REG_MULTI_SZ))
445 dwcbData =
sizeof(value);
446 result = RegQueryValueExW(key, L
"DriverVersion",
nullptr,
nullptr,
447 reinterpret_cast<LPBYTE>(value), &dwcbData);
448 if (result != ERROR_SUCCESS)
453 aDriverVersion2 = o3tl::toU(value);
454 dwcbData =
sizeof(value);
455 result = RegQueryValueExW(key, L
"DriverDate",
nullptr,
nullptr,
456 reinterpret_cast<LPBYTE>(value), &dwcbData);
457 if (result != ERROR_SUCCESS)
462 aDriverDate2 = o3tl::toU(value);
463 dwcbData =
sizeof(value);
464 result = RegQueryValueExW(key, L
"Device Description",
nullptr,
465 nullptr, reinterpret_cast<LPBYTE>(value), &dwcbData);
466 if (result != ERROR_SUCCESS)
468 dwcbData =
sizeof(value);
469 result = RegQueryValueExW(key, L
"DriverDesc",
nullptr,
nullptr,
470 reinterpret_cast<LPBYTE>(value), &dwcbData);
473 if (result == ERROR_SUCCESS)
490 SetupDiDestroyDeviceInfoList(devinfo);
virtual ~WinOpenGLDeviceInfo() override
bool FindBlocklistedDeviceInList()
OUString maDriverVersion2
SvStream & WriteOString(const OString &rStr)
SvStream & WriteCharPtr(const char *pBuf)
static OUString getDenylistFile()
bool IsDeviceBlocked(const OUString &blocklistURL, VersionType versionType, std::u16string_view driverVersion, std::u16string_view vendorId, const OUString &deviceId)
virtual bool isDeviceBlocked() override
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
OUString maAdapterVendorID2
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define SAL_N_ELEMENTS(arr)
#define SAL_CONFIGFILE(name)
OUString maAdapterSubsysID2
std::unique_ptr< char[]> aBuffer
OUString maAdapterSubsysID
#define DEVICE_KEY_PREFIX
#define SAL_INFO(area, stream)
OUString maAdapterVendorID
SvStream & WriteChar(char nChar)
OUString maAdapterDeviceID2
#define SAL_WARN(area, stream)
OUString maAdapterDeviceID
static void addKeyValue(SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER tAddKeyHandling)