769 lines
22 KiB
C++
769 lines
22 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <driverblocklist.hxx>
|
|
|
|
#include <algorithm>
|
|
#include <string_view>
|
|
|
|
#include <sal/log.hxx>
|
|
#include <utility>
|
|
|
|
#ifdef _WIN32
|
|
#if !defined WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
namespace DriverBlocklist
|
|
{
|
|
static OperatingSystem getOperatingSystem(std::string_view rString)
|
|
{
|
|
if (rString == "all")
|
|
return DRIVER_OS_ALL;
|
|
else if (rString == "7")
|
|
return DRIVER_OS_WINDOWS_7;
|
|
else if (rString == "8")
|
|
return DRIVER_OS_WINDOWS_8;
|
|
else if (rString == "8_1")
|
|
return DRIVER_OS_WINDOWS_8_1;
|
|
else if (rString == "10")
|
|
return DRIVER_OS_WINDOWS_10;
|
|
else if (rString == "windows")
|
|
return DRIVER_OS_WINDOWS_ALL;
|
|
else if (rString == "linux")
|
|
return DRIVER_OS_LINUX;
|
|
else if (rString == "osx_10_5")
|
|
return DRIVER_OS_OSX_10_5;
|
|
else if (rString == "osx_10_6")
|
|
return DRIVER_OS_OSX_10_6;
|
|
else if (rString == "osx_10_7")
|
|
return DRIVER_OS_OSX_10_7;
|
|
else if (rString == "osx_10_8")
|
|
return DRIVER_OS_OSX_10_8;
|
|
else if (rString == "osx")
|
|
return DRIVER_OS_OSX_ALL;
|
|
else if (rString == "android")
|
|
return DRIVER_OS_ANDROID;
|
|
return DRIVER_OS_UNKNOWN;
|
|
}
|
|
|
|
static VersionComparisonOp getComparison(std::string_view rString)
|
|
{
|
|
if (rString == "less")
|
|
{
|
|
return DRIVER_LESS_THAN;
|
|
}
|
|
else if (rString == "less_equal")
|
|
{
|
|
return DRIVER_LESS_THAN_OR_EQUAL;
|
|
}
|
|
else if (rString == "greater")
|
|
{
|
|
return DRIVER_GREATER_THAN;
|
|
}
|
|
else if (rString == "greater_equal")
|
|
{
|
|
return DRIVER_GREATER_THAN_OR_EQUAL;
|
|
}
|
|
else if (rString == "equal")
|
|
{
|
|
return DRIVER_EQUAL;
|
|
}
|
|
else if (rString == "not_equal")
|
|
{
|
|
return DRIVER_NOT_EQUAL;
|
|
}
|
|
else if (rString == "between_exclusive")
|
|
{
|
|
return DRIVER_BETWEEN_EXCLUSIVE;
|
|
}
|
|
else if (rString == "between_inclusive")
|
|
{
|
|
return DRIVER_BETWEEN_INCLUSIVE;
|
|
}
|
|
else if (rString == "between_inclusive_start")
|
|
{
|
|
return DRIVER_BETWEEN_INCLUSIVE_START;
|
|
}
|
|
|
|
throw InvalidFileException();
|
|
}
|
|
|
|
static OUString GetVendorId(std::string_view rString)
|
|
{
|
|
if (rString == "all")
|
|
{
|
|
return u""_ustr;
|
|
}
|
|
else if (rString == "intel")
|
|
{
|
|
return u"0x8086"_ustr;
|
|
}
|
|
else if (rString == "nvidia")
|
|
{
|
|
return u"0x10de"_ustr;
|
|
}
|
|
else if (rString == "amd")
|
|
{
|
|
return u"0x1002"_ustr;
|
|
}
|
|
else if (rString == "microsoft")
|
|
{
|
|
return u"0x1414"_ustr;
|
|
}
|
|
else
|
|
{
|
|
// Allow having simply the hex number as such there, too.
|
|
return OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
|
|
}
|
|
}
|
|
|
|
OUString GetVendorId(DeviceVendor id)
|
|
{
|
|
assert(id >= 0 && id < DeviceVendorMax);
|
|
|
|
switch (id)
|
|
{
|
|
case VendorAll:
|
|
return u""_ustr;
|
|
case VendorIntel:
|
|
return u"0x8086"_ustr;
|
|
case VendorNVIDIA:
|
|
return u"0x10de"_ustr;
|
|
case VendorAMD:
|
|
return u"0x1002"_ustr;
|
|
case VendorMicrosoft:
|
|
return u"0x1414"_ustr;
|
|
}
|
|
abort();
|
|
}
|
|
|
|
DeviceVendor GetVendorFromId(uint32_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case 0x8086:
|
|
return VendorIntel;
|
|
case 0x10de:
|
|
return VendorNVIDIA;
|
|
case 0x1002:
|
|
return VendorAMD;
|
|
case 0x1414:
|
|
return VendorMicrosoft;
|
|
default:
|
|
return VendorAll;
|
|
}
|
|
}
|
|
|
|
std::string_view GetVendorNameFromId(uint32_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case 0x8086:
|
|
return "Intel";
|
|
case 0x10de:
|
|
return "Nvidia";
|
|
case 0x1002:
|
|
return "AMD";
|
|
case 0x1414:
|
|
return "Microsoft";
|
|
default:
|
|
return "?";
|
|
}
|
|
}
|
|
|
|
Parser::Parser(OUString aURL, std::vector<DriverInfo>& rDriverList, VersionType versionType)
|
|
: meBlockType(BlockType::UNKNOWN)
|
|
, mrDriverList(rDriverList)
|
|
, maURL(std::move(aURL))
|
|
, mVersionType(versionType)
|
|
{
|
|
}
|
|
|
|
bool Parser::parse()
|
|
{
|
|
try
|
|
{
|
|
xmlreader::XmlReader aReader(maURL);
|
|
handleContent(aReader);
|
|
}
|
|
catch (...)
|
|
{
|
|
mrDriverList.clear();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// This allows us to pad driver version 'substrings' with 0s, this
|
|
// effectively allows us to treat the version numbers as 'decimals'. This is
|
|
// a little strange but this method seems to do the right thing for all
|
|
// different vendor's driver strings. i.e. .98 will become 9800, which is
|
|
// larger than .978 which would become 9780.
|
|
static void PadDriverDecimal(char* aString)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (!aString[i])
|
|
{
|
|
for (int c = i; c < 4; c++)
|
|
{
|
|
aString[c] = '0';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
aString[4] = 0;
|
|
}
|
|
|
|
// All destination string storage needs to have at least 5 bytes available.
|
|
static bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr, char* aCStr,
|
|
char* aDStr, VersionType versionType)
|
|
{
|
|
// sscanf doesn't do what we want here to we parse this manually.
|
|
int len = strlen(aSource);
|
|
char* dest[4] = { aAStr, aBStr, aCStr, aDStr };
|
|
unsigned destIdx = 0;
|
|
unsigned destPos = 0;
|
|
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
if (destIdx >= SAL_N_ELEMENTS(dest))
|
|
{
|
|
// Invalid format found. Ensure we don't access dest beyond bounds.
|
|
return false;
|
|
}
|
|
|
|
if (aSource[i] == '.')
|
|
{
|
|
dest[destIdx++][destPos] = 0;
|
|
destPos = 0;
|
|
continue;
|
|
}
|
|
|
|
if (destPos > 3)
|
|
{
|
|
// Ignore more than 4 chars. Ensure we never access dest[destIdx]
|
|
// beyond its bounds.
|
|
continue;
|
|
}
|
|
|
|
dest[destIdx][destPos++] = aSource[i];
|
|
}
|
|
|
|
// Add last terminator.
|
|
dest[destIdx][destPos] = 0;
|
|
|
|
// Vulkan version numbers have only 3 fields.
|
|
if (versionType == VersionType::Vulkan && destIdx == SAL_N_ELEMENTS(dest) - 2)
|
|
dest[++destIdx][0] = '\0';
|
|
if (destIdx != SAL_N_ELEMENTS(dest) - 1)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool ParseDriverVersion(std::u16string_view aVersion, uint64_t& rNumericVersion,
|
|
VersionType versionType)
|
|
{
|
|
rNumericVersion = 0;
|
|
|
|
int a, b, c, d;
|
|
char aStr[8], bStr[8], cStr[8], dStr[8];
|
|
/* honestly, why do I even bother */
|
|
OString aOVersion = OUStringToOString(aVersion, RTL_TEXTENCODING_UTF8);
|
|
if (!SplitDriverVersion(aOVersion.getStr(), aStr, bStr, cStr, dStr, versionType))
|
|
return false;
|
|
|
|
if (versionType == VersionType::OpenGL)
|
|
{
|
|
PadDriverDecimal(bStr);
|
|
PadDriverDecimal(cStr);
|
|
PadDriverDecimal(dStr);
|
|
}
|
|
|
|
a = atoi(aStr);
|
|
b = atoi(bStr);
|
|
c = atoi(cStr);
|
|
d = atoi(dStr);
|
|
|
|
if (versionType == VersionType::Vulkan)
|
|
assert(d == 0);
|
|
|
|
if (a < 0 || a > 0xffff)
|
|
return false;
|
|
if (b < 0 || b > 0xffff)
|
|
return false;
|
|
if (c < 0 || c > 0xffff)
|
|
return false;
|
|
if (d < 0 || d > 0xffff)
|
|
return false;
|
|
|
|
rNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
|
|
return true;
|
|
}
|
|
|
|
uint64_t Parser::getVersion(std::string_view rString)
|
|
{
|
|
OUString aString = OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
|
|
uint64_t nVersion;
|
|
bool bResult = ParseDriverVersion(aString, nVersion, mVersionType);
|
|
|
|
if (!bResult)
|
|
{
|
|
throw InvalidFileException();
|
|
}
|
|
|
|
return nVersion;
|
|
}
|
|
|
|
void Parser::handleDevices(DriverInfo& rDriver, xmlreader::XmlReader& rReader)
|
|
{
|
|
int nLevel = 1;
|
|
bool bInMsg = false;
|
|
|
|
while (true)
|
|
{
|
|
xmlreader::Span name;
|
|
int nsId;
|
|
|
|
xmlreader::XmlReader::Result res
|
|
= rReader.nextItem(xmlreader::XmlReader::Text::Normalized, &name, &nsId);
|
|
|
|
if (res == xmlreader::XmlReader::Result::Begin)
|
|
{
|
|
++nLevel;
|
|
if (nLevel > 2)
|
|
throw InvalidFileException();
|
|
|
|
if (name == "msg")
|
|
{
|
|
bInMsg = true;
|
|
}
|
|
else if (name == "device")
|
|
{
|
|
int nsIdDeveice;
|
|
while (rReader.nextAttribute(&nsIdDeveice, &name))
|
|
{
|
|
if (name == "id")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString aDeviceId(name.begin, name.length);
|
|
rDriver.maDevices.push_back(
|
|
OStringToOUString(aDeviceId, RTL_TEXTENCODING_UTF8));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
throw InvalidFileException();
|
|
}
|
|
else if (res == xmlreader::XmlReader::Result::End)
|
|
{
|
|
--nLevel;
|
|
bInMsg = false;
|
|
if (!nLevel)
|
|
break;
|
|
}
|
|
else if (res == xmlreader::XmlReader::Result::Text)
|
|
{
|
|
if (bInMsg)
|
|
{
|
|
OString sMsg(name.begin, name.length);
|
|
rDriver.maMsg = OStringToOUString(sMsg, RTL_TEXTENCODING_UTF8);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Parser::handleEntry(DriverInfo& rDriver, xmlreader::XmlReader& rReader)
|
|
{
|
|
if (meBlockType == BlockType::ALLOWLIST)
|
|
{
|
|
rDriver.mbAllowlisted = true;
|
|
}
|
|
else if (meBlockType == BlockType::DENYLIST)
|
|
{
|
|
rDriver.mbAllowlisted = false;
|
|
}
|
|
else if (meBlockType == BlockType::UNKNOWN)
|
|
{
|
|
throw InvalidFileException();
|
|
}
|
|
|
|
xmlreader::Span name;
|
|
int nsId;
|
|
|
|
while (rReader.nextAttribute(&nsId, &name))
|
|
{
|
|
if (name == "os")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sOS(name.begin, name.length);
|
|
rDriver.meOperatingSystem = getOperatingSystem(sOS);
|
|
}
|
|
else if (name == "vendor")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sVendor(name.begin, name.length);
|
|
rDriver.maAdapterVendor = GetVendorId(sVendor);
|
|
}
|
|
else if (name == "compare")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sCompare(name.begin, name.length);
|
|
rDriver.meComparisonOp = getComparison(sCompare);
|
|
}
|
|
else if (name == "version")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sVersion(name.begin, name.length);
|
|
rDriver.mnDriverVersion = getVersion(sVersion);
|
|
}
|
|
else if (name == "minVersion")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sMinVersion(name.begin, name.length);
|
|
rDriver.mnDriverVersion = getVersion(sMinVersion);
|
|
}
|
|
else if (name == "maxVersion")
|
|
{
|
|
name = rReader.getAttributeValue(false);
|
|
OString sMaxVersion(name.begin, name.length);
|
|
rDriver.mnDriverVersionMax = getVersion(sMaxVersion);
|
|
}
|
|
else
|
|
{
|
|
OString aAttrName(name.begin, name.length);
|
|
SAL_WARN("vcl.driver", "unsupported attribute: " << aAttrName);
|
|
}
|
|
}
|
|
|
|
handleDevices(rDriver, rReader);
|
|
}
|
|
|
|
void Parser::handleList(xmlreader::XmlReader& rReader)
|
|
{
|
|
xmlreader::Span name;
|
|
int nsId;
|
|
|
|
while (true)
|
|
{
|
|
xmlreader::XmlReader::Result res
|
|
= rReader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
|
|
if (res == xmlreader::XmlReader::Result::Begin)
|
|
{
|
|
if (name == "entry")
|
|
{
|
|
DriverInfo aDriver;
|
|
handleEntry(aDriver, rReader);
|
|
mrDriverList.push_back(aDriver);
|
|
}
|
|
else if (name == "entryRange")
|
|
{
|
|
DriverInfo aDriver;
|
|
handleEntry(aDriver, rReader);
|
|
mrDriverList.push_back(aDriver);
|
|
}
|
|
else
|
|
{
|
|
throw InvalidFileException();
|
|
}
|
|
}
|
|
else if (res == xmlreader::XmlReader::Result::End)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Parser::handleContent(xmlreader::XmlReader& rReader)
|
|
{
|
|
while (true)
|
|
{
|
|
xmlreader::Span name;
|
|
int nsId;
|
|
|
|
xmlreader::XmlReader::Result res
|
|
= rReader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
|
|
if (res == xmlreader::XmlReader::Result::Begin)
|
|
{
|
|
if (name == "allowlist")
|
|
{
|
|
meBlockType = BlockType::ALLOWLIST;
|
|
handleList(rReader);
|
|
}
|
|
else if (name == "denylist")
|
|
{
|
|
meBlockType = BlockType::DENYLIST;
|
|
handleList(rReader);
|
|
}
|
|
else if (name == "root")
|
|
{
|
|
}
|
|
else
|
|
{
|
|
throw InvalidFileException();
|
|
}
|
|
}
|
|
else if (res == xmlreader::XmlReader::Result::End)
|
|
{
|
|
if (name == "allowlist" || name == "denylist")
|
|
{
|
|
meBlockType = BlockType::UNKNOWN;
|
|
}
|
|
}
|
|
else if (res == xmlreader::XmlReader::Result::Done)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static OperatingSystem getOperatingSystem()
|
|
{
|
|
#ifdef _WIN32
|
|
// OS version in 16.16 major/minor form
|
|
// based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
|
|
switch (DriverBlocklist::GetWindowsVersion())
|
|
{
|
|
case 0x00060001:
|
|
return DRIVER_OS_WINDOWS_7;
|
|
case 0x00060002:
|
|
return DRIVER_OS_WINDOWS_8;
|
|
case 0x00060003:
|
|
return DRIVER_OS_WINDOWS_8_1;
|
|
case 0x000A0000: // Major 10 Minor 0
|
|
return DRIVER_OS_WINDOWS_10;
|
|
default:
|
|
return DRIVER_OS_UNKNOWN;
|
|
}
|
|
#elif defined LINUX
|
|
return DRIVER_OS_LINUX;
|
|
#else
|
|
return DRIVER_OS_UNKNOWN;
|
|
#endif
|
|
}
|
|
|
|
namespace
|
|
{
|
|
struct compareIgnoreAsciiCase
|
|
{
|
|
explicit compareIgnoreAsciiCase(OUString aString)
|
|
: maString(std::move(aString))
|
|
{
|
|
}
|
|
|
|
bool operator()(std::u16string_view rCompare)
|
|
{
|
|
return maString.equalsIgnoreAsciiCase(rCompare);
|
|
}
|
|
|
|
private:
|
|
OUString maString;
|
|
};
|
|
}
|
|
|
|
const uint64_t allDriverVersions = ~(uint64_t(0));
|
|
|
|
DriverInfo::DriverInfo()
|
|
: meOperatingSystem(DRIVER_OS_UNKNOWN)
|
|
, maAdapterVendor(GetVendorId(VendorAll))
|
|
, mbAllowlisted(false)
|
|
, meComparisonOp(DRIVER_COMPARISON_IGNORED)
|
|
, mnDriverVersion(0)
|
|
, mnDriverVersionMax(0)
|
|
{
|
|
}
|
|
|
|
DriverInfo::DriverInfo(OperatingSystem os, OUString vendor, VersionComparisonOp op,
|
|
uint64_t driverVersion, bool bAllowlisted,
|
|
const char* suggestedVersion /* = nullptr */)
|
|
: meOperatingSystem(os)
|
|
, maAdapterVendor(std::move(vendor))
|
|
, mbAllowlisted(bAllowlisted)
|
|
, meComparisonOp(op)
|
|
, mnDriverVersion(driverVersion)
|
|
, mnDriverVersionMax(0)
|
|
{
|
|
if (suggestedVersion)
|
|
maSuggestedVersion
|
|
= OStringToOUString(std::string_view(suggestedVersion), RTL_TEXTENCODING_UTF8);
|
|
}
|
|
|
|
bool FindBlocklistedDeviceInList(std::vector<DriverInfo>& aDeviceInfos, VersionType versionType,
|
|
std::u16string_view sDriverVersion,
|
|
std::u16string_view sAdapterVendorID,
|
|
OUString const& sAdapterDeviceID, OperatingSystem system,
|
|
const OUString& blocklistURL)
|
|
{
|
|
uint64_t driverVersion;
|
|
ParseDriverVersion(sDriverVersion, driverVersion, versionType);
|
|
|
|
bool match = false;
|
|
for (const auto& rDeviceInfo : aDeviceInfos)
|
|
{
|
|
bool osMatch = false;
|
|
if (rDeviceInfo.meOperatingSystem == DRIVER_OS_ALL)
|
|
osMatch = true;
|
|
else if (rDeviceInfo.meOperatingSystem == system)
|
|
osMatch = true;
|
|
else if (rDeviceInfo.meOperatingSystem == DRIVER_OS_WINDOWS_ALL
|
|
&& system >= DRIVER_OS_WINDOWS_FIRST && system <= DRIVER_OS_WINDOWS_LAST)
|
|
osMatch = true;
|
|
else if (rDeviceInfo.meOperatingSystem == DRIVER_OS_OSX_ALL && system >= DRIVER_OS_OSX_FIRST
|
|
&& system <= DRIVER_OS_OSX_LAST)
|
|
osMatch = true;
|
|
if (!osMatch)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!rDeviceInfo.maAdapterVendor.equalsIgnoreAsciiCase(GetVendorId(VendorAll))
|
|
&& !rDeviceInfo.maAdapterVendor.equalsIgnoreAsciiCase(sAdapterVendorID))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (std::none_of(rDeviceInfo.maDevices.begin(), rDeviceInfo.maDevices.end(),
|
|
compareIgnoreAsciiCase(u"all"_ustr))
|
|
&& std::none_of(rDeviceInfo.maDevices.begin(), rDeviceInfo.maDevices.end(),
|
|
compareIgnoreAsciiCase(sAdapterDeviceID)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
switch (rDeviceInfo.meComparisonOp)
|
|
{
|
|
case DRIVER_LESS_THAN:
|
|
match = driverVersion < rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_LESS_THAN_OR_EQUAL:
|
|
match = driverVersion <= rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_GREATER_THAN:
|
|
match = driverVersion > rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_GREATER_THAN_OR_EQUAL:
|
|
match = driverVersion >= rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_EQUAL:
|
|
match = driverVersion == rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_NOT_EQUAL:
|
|
match = driverVersion != rDeviceInfo.mnDriverVersion;
|
|
break;
|
|
case DRIVER_BETWEEN_EXCLUSIVE:
|
|
match = driverVersion > rDeviceInfo.mnDriverVersion
|
|
&& driverVersion < rDeviceInfo.mnDriverVersionMax;
|
|
break;
|
|
case DRIVER_BETWEEN_INCLUSIVE:
|
|
match = driverVersion >= rDeviceInfo.mnDriverVersion
|
|
&& driverVersion <= rDeviceInfo.mnDriverVersionMax;
|
|
break;
|
|
case DRIVER_BETWEEN_INCLUSIVE_START:
|
|
match = driverVersion >= rDeviceInfo.mnDriverVersion
|
|
&& driverVersion < rDeviceInfo.mnDriverVersionMax;
|
|
break;
|
|
case DRIVER_COMPARISON_IGNORED:
|
|
// We don't have a comparison op, so we match everything.
|
|
match = true;
|
|
break;
|
|
default:
|
|
SAL_WARN("vcl.driver", "Bogus op in " << blocklistURL);
|
|
break;
|
|
}
|
|
|
|
if (match || rDeviceInfo.mnDriverVersion == allDriverVersions)
|
|
{
|
|
// white listed drivers
|
|
if (rDeviceInfo.mbAllowlisted)
|
|
{
|
|
SAL_INFO("vcl.driver", "allowlisted driver");
|
|
return false;
|
|
}
|
|
|
|
match = true;
|
|
if (!rDeviceInfo.maSuggestedVersion.isEmpty())
|
|
{
|
|
SAL_WARN("vcl.driver", "use : " << rDeviceInfo.maSuggestedVersion);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
SAL_INFO("vcl.driver", (match ? "denylisted" : "not denylisted") << " in " << blocklistURL);
|
|
return match;
|
|
}
|
|
|
|
bool IsDeviceBlocked(const OUString& blocklistURL, VersionType versionType,
|
|
std::u16string_view driverVersion, std::u16string_view vendorId,
|
|
const OUString& deviceId)
|
|
{
|
|
std::vector<DriverInfo> driverList;
|
|
Parser parser(blocklistURL, driverList, versionType);
|
|
if (!parser.parse())
|
|
{
|
|
SAL_WARN("vcl.driver", "error parsing denylist " << blocklistURL);
|
|
return false;
|
|
}
|
|
return FindBlocklistedDeviceInList(driverList, versionType, driverVersion, vendorId, deviceId,
|
|
getOperatingSystem(), blocklistURL);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
int32_t GetWindowsVersion()
|
|
{
|
|
static int32_t winVersion = []() {
|
|
// GetVersion(Ex) and VersionHelpers (based on VerifyVersionInfo) API are
|
|
// subject to manifest-based behavior since Windows 8.1, so give wrong results.
|
|
// Another approach would be to use NetWkstaGetInfo, but that has some small
|
|
// reported delays (some milliseconds), and might get slower in domains with
|
|
// poor network connections.
|
|
// So go with a solution described at https://msdn.microsoft.com/en-us/library/ms724429
|
|
HINSTANCE hLibrary = LoadLibraryW(L"kernel32.dll");
|
|
if (hLibrary != nullptr)
|
|
{
|
|
wchar_t szPath[MAX_PATH];
|
|
DWORD dwCount = GetModuleFileNameW(hLibrary, szPath, SAL_N_ELEMENTS(szPath));
|
|
FreeLibrary(hLibrary);
|
|
if (dwCount != 0 && dwCount < SAL_N_ELEMENTS(szPath))
|
|
{
|
|
dwCount = GetFileVersionInfoSizeW(szPath, nullptr);
|
|
if (dwCount != 0)
|
|
{
|
|
std::unique_ptr<char[]> ver(new char[dwCount]);
|
|
if (GetFileVersionInfoW(szPath, 0, dwCount, ver.get()) != FALSE)
|
|
{
|
|
void* pBlock = nullptr;
|
|
UINT dwBlockSz = 0;
|
|
if (VerQueryValueW(ver.get(), L"\\", &pBlock, &dwBlockSz) != FALSE
|
|
&& dwBlockSz >= sizeof(VS_FIXEDFILEINFO))
|
|
{
|
|
VS_FIXEDFILEINFO* vinfo = static_cast<VS_FIXEDFILEINFO*>(pBlock);
|
|
return int32_t(vinfo->dwProductVersionMS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}();
|
|
|
|
return winVersion;
|
|
}
|
|
#endif
|
|
|
|
} // namespace
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|