Bug 1313339 - Also use modules loaded in the process to decide about DXVA blocklisting. r=gerald

This commit is contained in:
Marco Castelluccio 2016-12-24 10:17:46 +01:00
Родитель 37e6ad7e9e
Коммит 533966fbc4
1 изменённых файлов: 90 добавлений и 54 удалений

Просмотреть файл

@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include <winsdkver.h> #include <winsdkver.h>
#include <psapi.h>
#include "WMFVideoMFTManager.h" #include "WMFVideoMFTManager.h"
#include "MediaDecoderReader.h" #include "MediaDecoderReader.h"
#include "gfxPrefs.h" #include "gfxPrefs.h"
@ -196,6 +197,17 @@ FindDXVABlacklistedDLL(StaticAutoPtr<D3DDLLBlacklistingCache>& aDLLBlacklistingC
// Adopt new pref now, so we don't work on it again. // Adopt new pref now, so we don't work on it again.
aDLLBlacklistingCache->mBlacklistPref = aBlacklist; aDLLBlacklistingCache->mBlacklistPref = aBlacklist;
HANDLE hProcess = GetCurrentProcess();
mozilla::UniquePtr<HMODULE[]> hMods;
unsigned int modulesNum = 0;
if (hProcess != NULL) {
DWORD modulesSize;
EnumProcessModules(hProcess, nullptr, 0, &modulesSize);
modulesNum = modulesSize / sizeof(HMODULE);
hMods = mozilla::MakeUnique<HMODULE[]>(modulesNum);
EnumProcessModules(hProcess, hMods.get(), modulesNum * sizeof(HMODULE), &modulesSize);
}
// media.wmf.disable-d3d*-for-dlls format: (whitespace is trimmed) // media.wmf.disable-d3d*-for-dlls format: (whitespace is trimmed)
// "dll1.dll: 1.2.3.4[, more versions...][; more dlls...]" // "dll1.dll: 1.2.3.4[, more versions...][; more dlls...]"
nsTArray<nsCString> dlls; nsTArray<nsCString> dlls;
@ -211,68 +223,92 @@ FindDXVABlacklistedDLL(StaticAutoPtr<D3DDLLBlacklistingCache>& aDLLBlacklistingC
nameAndVersions[0].CompressWhitespace(); nameAndVersions[0].CompressWhitespace();
NS_ConvertUTF8toUTF16 name(nameAndVersions[0]); NS_ConvertUTF8toUTF16 name(nameAndVersions[0]);
WCHAR systemPath[MAX_PATH + 1];
if (!ConstructSystem32Path(name.get(), systemPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
continue;
}
DWORD zero; for (unsigned int i = 0; i <= modulesNum; i++) {
DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero); WCHAR dllPath[MAX_PATH + 1];
if (infoSize == 0) {
// Can't get file info -> Assume we don't have the blacklisted DLL.
continue;
}
// vInfo is a pointer into infoData, that's why we keep it outside of the loop.
auto infoData = MakeUnique<unsigned char[]>(infoSize);
VS_FIXEDFILEINFO *vInfo;
UINT vInfoLen;
if (!GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get())
|| !VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)
|| !vInfo) {
// Can't find version -> Assume it's not blacklisted.
continue;
}
nsTArray<nsCString> versions; if (i < modulesNum) {
SplitAt(",", nameAndVersions[1], versions); if (!GetModuleFileNameEx(hProcess, hMods[i], dllPath, sizeof(dllPath) / sizeof(WCHAR))) {
for (const auto& version : versions) { continue;
nsTArray<nsCString> numberStrings; }
SplitAt(".", version, numberStrings);
if (numberStrings.Length() != 4) { nsCOMPtr<nsIFile> file;
NS_WARNING(nsPrintfCString("Skipping incorrect '%s' a.b.c.d version format", if (NS_WARN_IF(NS_FAILED(NS_NewLocalFile(nsDependentString(dllPath), false, getter_AddRefs(file))))) {
aDLLBlacklistPrefName).get()); continue;
}
nsAutoString leafName;
if (NS_WARN_IF(NS_FAILED(file->GetLeafName(leafName)))) {
continue;
}
if (_wcsicmp(leafName.get(), name.get())) {
continue;
}
} else {
if (!ConstructSystem32Path(name.get(), dllPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
continue;
}
}
DWORD zero;
DWORD infoSize = GetFileVersionInfoSizeW(dllPath, &zero);
if (infoSize == 0) {
// Can't get file info -> Assume we don't have the blacklisted DLL.
continue; continue;
} }
DWORD numbers[4]; // vInfo is a pointer into infoData, that's why we keep it outside of the loop.
nsresult errorCode = NS_OK; auto infoData = MakeUnique<unsigned char[]>(infoSize);
for (int i = 0; i < 4; ++i) { VS_FIXEDFILEINFO *vInfo;
numberStrings[i].CompressWhitespace(); UINT vInfoLen;
numbers[i] = DWORD(numberStrings[i].ToInteger(&errorCode)); if (!GetFileVersionInfoW(dllPath, 0, infoSize, infoData.get())
|| !VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)
|| !vInfo) {
// Can't find version -> Assume it's not blacklisted.
continue;
}
nsTArray<nsCString> versions;
SplitAt(",", nameAndVersions[1], versions);
for (const auto& version : versions) {
nsTArray<nsCString> numberStrings;
SplitAt(".", version, numberStrings);
if (numberStrings.Length() != 4) {
NS_WARNING(nsPrintfCString("Skipping incorrect '%s' a.b.c.d version format",
aDLLBlacklistPrefName).get());
continue;
}
DWORD numbers[4];
nsresult errorCode = NS_OK;
for (int i = 0; i < 4; ++i) {
numberStrings[i].CompressWhitespace();
numbers[i] = DWORD(numberStrings[i].ToInteger(&errorCode));
if (NS_FAILED(errorCode)) {
break;
}
if (numbers[i] > UINT16_MAX) {
errorCode = NS_ERROR_FAILURE;
break;
}
}
if (NS_FAILED(errorCode)) { if (NS_FAILED(errorCode)) {
break; NS_WARNING(nsPrintfCString("Skipping incorrect '%s' a.b.c.d version format",
aDLLBlacklistPrefName).get());
continue;
} }
if (numbers[i] > UINT16_MAX) {
errorCode = NS_ERROR_FAILURE; if (vInfo->dwFileVersionMS == ((numbers[0] << 16) | numbers[1])
break; && vInfo->dwFileVersionLS == ((numbers[2] << 16) | numbers[3])) {
// Blacklisted! Record bad DLL.
aDLLBlacklistingCache->mBlacklistedDLL.SetLength(0);
aDLLBlacklistingCache->mBlacklistedDLL.AppendPrintf(
"%s (%lu.%lu.%lu.%lu)",
nameAndVersions[0].get(), numbers[0], numbers[1], numbers[2], numbers[3]);
return aDLLBlacklistingCache->mBlacklistedDLL;
} }
} }
if (NS_FAILED(errorCode)) {
NS_WARNING(nsPrintfCString("Skipping incorrect '%s' a.b.c.d version format",
aDLLBlacklistPrefName).get());
continue;
}
if (vInfo->dwFileVersionMS == ((numbers[0] << 16) | numbers[1])
&& vInfo->dwFileVersionLS == ((numbers[2] << 16) | numbers[3])) {
// Blacklisted! Record bad DLL.
aDLLBlacklistingCache->mBlacklistedDLL.SetLength(0);
aDLLBlacklistingCache->mBlacklistedDLL.AppendPrintf(
"%s (%lu.%lu.%lu.%lu)",
nameAndVersions[0].get(), numbers[0], numbers[1], numbers[2], numbers[3]);
return aDLLBlacklistingCache->mBlacklistedDLL;
}
} }
} }