зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1313339 - Also use modules loaded in the process to decide about DXVA blocklisting. r=gerald
This commit is contained in:
Родитель
37e6ad7e9e
Коммит
533966fbc4
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче