Bug 1313339 - Also use modules loaded in the process to decide about DXVA blocklisting. r=gerald, a=lizzard
authorMarco Castelluccio <mcastelluccio@mozilla.com>
Sat, 24 Dec 2016 10:17:46 +0100
changeset 353273 c577d43a2444d9533eed23a87aea7e22dd6c2d81
parent 353272 44f224d54b4c36765879cbfc66d0006280739984
child 353274 907b98f8c6fadbcad27e1c13c7d3645bc1109368
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald, lizzard
bugs1313339
milestone52.0a2
Bug 1313339 - Also use modules loaded in the process to decide about DXVA blocklisting. r=gerald, a=lizzard
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 <algorithm>
 #include <winsdkver.h>
+#include <psapi.h>
 #include "WMFVideoMFTManager.h"
 #include "MediaDecoderReader.h"
 #include "gfxPrefs.h"
 #include "WMFUtils.h"
 #include "ImageContainer.h"
 #include "VideoUtils.h"
 #include "DXVA2Manager.h"
 #include "nsThreadUtils.h"
@@ -191,92 +192,127 @@ FindDXVABlacklistedDLL(StaticAutoPtr<D3D
   // Detect changes in pref.
   if (aDLLBlacklistingCache->mBlacklistPref.Equals(aBlacklist)) {
     // Same blacklist -> Return same result (i.e., don't check DLLs again).
     return aDLLBlacklistingCache->mBlacklistedDLL;
   }
   // Adopt new pref now, so we don't work on it again.
   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)
   // "dll1.dll: 1.2.3.4[, more versions...][; more dlls...]"
   nsTArray<nsCString> dlls;
   SplitAt(";", aBlacklist, dlls);
   for (const auto& dll : dlls) {
     nsTArray<nsCString> nameAndVersions;
     SplitAt(":", dll, nameAndVersions);
     if (nameAndVersions.Length() != 2) {
       NS_WARNING(nsPrintfCString("Skipping incorrect '%s' dll:versions format",
                                  aDLLBlacklistPrefName).get());
       continue;
     }
 
     nameAndVersions[0].CompressWhitespace();
     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;
-    }
+
+    for (unsigned int i = 0; i <= modulesNum; i++) {
+      WCHAR dllPath[MAX_PATH + 1];
+
+      if (i < modulesNum) {
+        if (!GetModuleFileNameEx(hProcess, hMods[i], dllPath, sizeof(dllPath) / sizeof(WCHAR))) {
+          continue;
+        }
 
-    DWORD zero;
-    DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
-    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;
-    }
+        nsCOMPtr<nsIFile> file;
+        if (NS_WARN_IF(NS_FAILED(NS_NewLocalFile(nsDependentString(dllPath), false, getter_AddRefs(file))))) {
+          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;
+        nsAutoString leafName;
+        if (NS_WARN_IF(NS_FAILED(file->GetLeafName(leafName)))) {
+          continue;
         }
-        if (numbers[i] > UINT16_MAX) {
-          errorCode = NS_ERROR_FAILURE;
-          break;
+
+        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;
         }
       }
 
-      if (NS_FAILED(errorCode)) {
-        NS_WARNING(nsPrintfCString("Skipping incorrect '%s' a.b.c.d version format",
-                                   aDLLBlacklistPrefName).get());
+      DWORD zero;
+      DWORD infoSize = GetFileVersionInfoSizeW(dllPath, &zero);
+      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(dllPath, 0, infoSize, infoData.get())
+          || !VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)
+          || !vInfo) {
+        // Can't find version -> Assume it's not blacklisted.
         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;
+      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)) {
+          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;
+        }
       }
     }
   }
 
   // No blacklisted DLL.
   aDLLBlacklistingCache->mBlacklistedDLL.SetLength(0);
   return aDLLBlacklistingCache->mBlacklistedDLL;
 }