static bool IsH264DecoderBlacklisted() { #ifdef BLACKLIST_CRASHY_H264_DECODERS WCHAR systemPath[MAX_PATH + 1]; if (!ConstructSystem32Path(L"msmpeg2vdec.dll", systemPath, MAX_PATH + 1)) { // Cannot build path -> Assume it's not the blacklisted DLL. return false; } DWORD zero; DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero); if (infoSize == 0) { // Can't get file info -> Assume we don't have the blacklisted DLL. return false; } 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)) { if ((vInfo->dwFileVersionMS == ((12u << 16) | 0u)) && ((vInfo->dwFileVersionLS == ((9200u << 16) | 16426u)) || (vInfo->dwFileVersionLS == ((9200u << 16) | 17037u)))) { // 12.0.9200.16426 & .17037 are blacklisted on Win64, see bug 1242343. return true; } } #endif // BLACKLIST_CRASHY_H264_DECODERS return false; }
// If a blacklisted DLL is found, return its information, otherwise "". static const nsACString& FindDXVABlacklistedDLL(StaticAutoPtr<D3DDLLBlacklistingCache>& aDLLBlacklistingCache, const char* aDLLBlacklistPrefName) { NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); if (!aDLLBlacklistingCache) { // First time here, create persistent data that will be reused in all // D3D11-blacklisting checks. aDLLBlacklistingCache = new D3DDLLBlacklistingCache(); ClearOnShutdown(&aDLLBlacklistingCache); } nsAdoptingCString blacklist = Preferences::GetCString(aDLLBlacklistPrefName); if (blacklist.IsEmpty()) { // Empty blacklist -> No blacklisting. aDLLBlacklistingCache->mBlacklistPref.SetLength(0); aDLLBlacklistingCache->mBlacklistedDLL.SetLength(0); return aDLLBlacklistingCache->mBlacklistedDLL; } // Detect changes in pref. if (aDLLBlacklistingCache->mBlacklistPref.Equals(blacklist)) { // 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 = blacklist; // media.wmf.disable-d3d*-for-dlls format: (whitespace is trimmed) // "dll1.dll: 1.2.3.4[, more versions...][; more dlls...]" nsTArray<nsCString> dlls; SplitAt(";", blacklist, 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; } 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; } 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; }