1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,438 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsPluginDirServiceProvider.h" 1.10 + 1.11 +#include "nsCRT.h" 1.12 +#include "nsIFile.h" 1.13 +#include "nsDependentString.h" 1.14 +#include "nsArrayEnumerator.h" 1.15 +#include "mozilla/Preferences.h" 1.16 + 1.17 +#include <windows.h> 1.18 +#include "nsIWindowsRegKey.h" 1.19 + 1.20 +using namespace mozilla; 1.21 + 1.22 +typedef struct structVer 1.23 +{ 1.24 + WORD wMajor; 1.25 + WORD wMinor; 1.26 + WORD wRelease; 1.27 + WORD wBuild; 1.28 +} verBlock; 1.29 + 1.30 +static void 1.31 +ClearVersion(verBlock *ver) 1.32 +{ 1.33 + ver->wMajor = 0; 1.34 + ver->wMinor = 0; 1.35 + ver->wRelease = 0; 1.36 + ver->wBuild = 0; 1.37 +} 1.38 + 1.39 +static BOOL 1.40 +FileExists(LPCWSTR szFile) 1.41 +{ 1.42 + return GetFileAttributesW(szFile) != 0xFFFFFFFF; 1.43 +} 1.44 + 1.45 +// Get file version information from a file 1.46 +static BOOL 1.47 +GetFileVersion(LPCWSTR szFile, verBlock *vbVersion) 1.48 +{ 1.49 + UINT uLen; 1.50 + UINT dwLen; 1.51 + BOOL bRv; 1.52 + DWORD dwHandle; 1.53 + LPVOID lpData; 1.54 + LPVOID lpBuffer; 1.55 + VS_FIXEDFILEINFO *lpBuffer2; 1.56 + 1.57 + ClearVersion(vbVersion); 1.58 + if (FileExists(szFile)) { 1.59 + bRv = TRUE; 1.60 + LPCWSTR lpFilepath = szFile; 1.61 + dwLen = GetFileVersionInfoSizeW(lpFilepath, &dwHandle); 1.62 + lpData = (LPVOID)malloc(dwLen); 1.63 + uLen = 0; 1.64 + 1.65 + if (lpData && GetFileVersionInfoW(lpFilepath, dwHandle, dwLen, lpData) != 0) { 1.66 + if (VerQueryValueW(lpData, L"\\", &lpBuffer, &uLen) != 0) { 1.67 + lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer; 1.68 + 1.69 + vbVersion->wMajor = HIWORD(lpBuffer2->dwFileVersionMS); 1.70 + vbVersion->wMinor = LOWORD(lpBuffer2->dwFileVersionMS); 1.71 + vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS); 1.72 + vbVersion->wBuild = LOWORD(lpBuffer2->dwFileVersionLS); 1.73 + } 1.74 + } 1.75 + 1.76 + free(lpData); 1.77 + } else { 1.78 + /* File does not exist */ 1.79 + bRv = FALSE; 1.80 + } 1.81 + 1.82 + return bRv; 1.83 +} 1.84 + 1.85 +// Will deep copy ver2 into ver1 1.86 +static void 1.87 +CopyVersion(verBlock *ver1, verBlock *ver2) 1.88 +{ 1.89 + ver1->wMajor = ver2->wMajor; 1.90 + ver1->wMinor = ver2->wMinor; 1.91 + ver1->wRelease = ver2->wRelease; 1.92 + ver1->wBuild = ver2->wBuild; 1.93 +} 1.94 + 1.95 +// Convert a string version to a version struct 1.96 +static void 1.97 +TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion) 1.98 +{ 1.99 + WCHAR* szNum1 = nullptr; 1.100 + WCHAR* szNum2 = nullptr; 1.101 + WCHAR* szNum3 = nullptr; 1.102 + WCHAR* szNum4 = nullptr; 1.103 + WCHAR* szJavaBuild = nullptr; 1.104 + 1.105 + WCHAR *strVer = nullptr; 1.106 + if (szVersion) { 1.107 + strVer = wcsdup(szVersion); 1.108 + } 1.109 + 1.110 + if (!strVer) { 1.111 + // Out of memory 1.112 + ClearVersion(vbVersion); 1.113 + return; 1.114 + } 1.115 + 1.116 + // Java may be using an underscore instead of a dot for the build ID 1.117 + szJavaBuild = wcschr(strVer, '_'); 1.118 + if (szJavaBuild) { 1.119 + szJavaBuild[0] = '.'; 1.120 + } 1.121 + 1.122 + szNum1 = wcstok(strVer, L"."); 1.123 + szNum2 = wcstok(nullptr, L"."); 1.124 + szNum3 = wcstok(nullptr, L"."); 1.125 + szNum4 = wcstok(nullptr, L"."); 1.126 + 1.127 + vbVersion->wMajor = szNum1 ? (WORD) _wtoi(szNum1) : 0; 1.128 + vbVersion->wMinor = szNum2 ? (WORD) _wtoi(szNum2) : 0; 1.129 + vbVersion->wRelease = szNum3 ? (WORD) _wtoi(szNum3) : 0; 1.130 + vbVersion->wBuild = szNum4 ? (WORD) _wtoi(szNum4) : 0; 1.131 + 1.132 + free(strVer); 1.133 +} 1.134 + 1.135 +// Compare two version struct, return zero if the same 1.136 +static int 1.137 +CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew) 1.138 +{ 1.139 + if (vbVersionOld.wMajor > vbVersionNew.wMajor) { 1.140 + return 4; 1.141 + } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) { 1.142 + return -4; 1.143 + } 1.144 + 1.145 + if (vbVersionOld.wMinor > vbVersionNew.wMinor) { 1.146 + return 3; 1.147 + } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) { 1.148 + return -3; 1.149 + } 1.150 + 1.151 + if (vbVersionOld.wRelease > vbVersionNew.wRelease) { 1.152 + return 2; 1.153 + } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) { 1.154 + return -2; 1.155 + } 1.156 + 1.157 + if (vbVersionOld.wBuild > vbVersionNew.wBuild) { 1.158 + return 1; 1.159 + } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) { 1.160 + return -1; 1.161 + } 1.162 + 1.163 + /* the versions are all the same */ 1.164 + return 0; 1.165 +} 1.166 + 1.167 +//***************************************************************************** 1.168 +// nsPluginDirServiceProvider::Constructor/Destructor 1.169 +//***************************************************************************** 1.170 + 1.171 +nsPluginDirServiceProvider::nsPluginDirServiceProvider() 1.172 +{ 1.173 +} 1.174 + 1.175 +nsPluginDirServiceProvider::~nsPluginDirServiceProvider() 1.176 +{ 1.177 +} 1.178 + 1.179 +//***************************************************************************** 1.180 +// nsPluginDirServiceProvider::nsISupports 1.181 +//***************************************************************************** 1.182 + 1.183 +NS_IMPL_ISUPPORTS(nsPluginDirServiceProvider, 1.184 + nsIDirectoryServiceProvider) 1.185 + 1.186 +//***************************************************************************** 1.187 +// nsPluginDirServiceProvider::nsIDirectoryServiceProvider 1.188 +//***************************************************************************** 1.189 + 1.190 +NS_IMETHODIMP 1.191 +nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant, 1.192 + nsIFile **_retval) 1.193 +{ 1.194 + nsCOMPtr<nsIFile> localFile; 1.195 + nsresult rv = NS_ERROR_FAILURE; 1.196 + 1.197 + NS_ENSURE_ARG(charProp); 1.198 + 1.199 + *_retval = nullptr; 1.200 + *persistant = false; 1.201 + 1.202 + nsCOMPtr<nsIWindowsRegKey> regKey = 1.203 + do_CreateInstance("@mozilla.org/windows-registry-key;1"); 1.204 + NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE); 1.205 + 1.206 + if (nsCRT::strcmp(charProp, NS_WIN_QUICKTIME_SCAN_KEY) == 0) { 1.207 + nsAdoptingCString strVer = Preferences::GetCString(charProp); 1.208 + if (!strVer) { 1.209 + return NS_ERROR_FAILURE; 1.210 + } 1.211 + verBlock minVer; 1.212 + TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer); 1.213 + 1.214 + // Look for the Quicktime system installation plugins directory 1.215 + verBlock qtVer; 1.216 + ClearVersion(&qtVer); 1.217 + 1.218 + // First we need to check the version of Quicktime via checking 1.219 + // the EXE's version table 1.220 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.221 + NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe"), 1.222 + nsIWindowsRegKey::ACCESS_READ); 1.223 + if (NS_SUCCEEDED(rv)) { 1.224 + nsAutoString path; 1.225 + rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path); 1.226 + if (NS_SUCCEEDED(rv)) { 1.227 + GetFileVersion(path.get(), &qtVer); 1.228 + } 1.229 + regKey->Close(); 1.230 + } 1.231 + if (CompareVersion(qtVer, minVer) < 0) 1.232 + return rv; 1.233 + 1.234 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.235 + NS_LITERAL_STRING("software\\Apple Computer, Inc.\\QuickTime"), 1.236 + nsIWindowsRegKey::ACCESS_READ); 1.237 + if (NS_SUCCEEDED(rv)) { 1.238 + nsAutoString path; 1.239 + rv = regKey->ReadStringValue(NS_LITERAL_STRING("InstallDir"), path); 1.240 + if (NS_SUCCEEDED(rv)) { 1.241 + path += NS_LITERAL_STRING("\\Plugins"); 1.242 + rv = NS_NewLocalFile(path, true, 1.243 + getter_AddRefs(localFile)); 1.244 + } 1.245 + } 1.246 + } else if (nsCRT::strcmp(charProp, NS_WIN_WMP_SCAN_KEY) == 0) { 1.247 + nsAdoptingCString strVer = Preferences::GetCString(charProp); 1.248 + if (!strVer) { 1.249 + return NS_ERROR_FAILURE; 1.250 + } 1.251 + verBlock minVer; 1.252 + TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer); 1.253 + 1.254 + // Look for Windows Media Player system installation plugins directory 1.255 + verBlock wmpVer; 1.256 + ClearVersion(&wmpVer); 1.257 + 1.258 + // First we need to check the version of WMP 1.259 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.260 + NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe"), 1.261 + nsIWindowsRegKey::ACCESS_READ); 1.262 + if (NS_SUCCEEDED(rv)) { 1.263 + nsAutoString path; 1.264 + rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path); 1.265 + if (NS_SUCCEEDED(rv)) { 1.266 + GetFileVersion(path.get(), &wmpVer); 1.267 + } 1.268 + regKey->Close(); 1.269 + } 1.270 + if (CompareVersion(wmpVer, minVer) < 0) 1.271 + return rv; 1.272 + 1.273 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.274 + NS_LITERAL_STRING("software\\Microsoft\\MediaPlayer"), 1.275 + nsIWindowsRegKey::ACCESS_READ); 1.276 + if (NS_SUCCEEDED(rv)) { 1.277 + nsAutoString path; 1.278 + rv = regKey->ReadStringValue(NS_LITERAL_STRING("Installation Directory"), 1.279 + path); 1.280 + if (NS_SUCCEEDED(rv)) { 1.281 + rv = NS_NewLocalFile(path, true, 1.282 + getter_AddRefs(localFile)); 1.283 + } 1.284 + } 1.285 + } else if (nsCRT::strcmp(charProp, NS_WIN_ACROBAT_SCAN_KEY) == 0) { 1.286 + nsAdoptingCString strVer = Preferences::GetCString(charProp); 1.287 + if (!strVer) { 1.288 + return NS_ERROR_FAILURE; 1.289 + } 1.290 + 1.291 + verBlock minVer; 1.292 + TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer); 1.293 + 1.294 + // Look for Adobe Acrobat system installation plugins directory 1.295 + verBlock maxVer; 1.296 + ClearVersion(&maxVer); 1.297 + 1.298 + nsAutoString newestPath; 1.299 + 1.300 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.301 + NS_LITERAL_STRING("software\\Adobe\\Acrobat Reader"), 1.302 + nsIWindowsRegKey::ACCESS_READ); 1.303 + if (NS_FAILED(rv)) { 1.304 + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, 1.305 + NS_LITERAL_STRING("software\\Adobe\\Adobe Acrobat"), 1.306 + nsIWindowsRegKey::ACCESS_READ); 1.307 + if (NS_FAILED(rv)) { 1.308 + return NS_ERROR_FAILURE; 1.309 + } 1.310 + } 1.311 + 1.312 + // We must enumerate through the keys because what if there is 1.313 + // more than one version? 1.314 + uint32_t childCount = 0; 1.315 + regKey->GetChildCount(&childCount); 1.316 + 1.317 + for (uint32_t index = 0; index < childCount; ++index) { 1.318 + nsAutoString childName; 1.319 + rv = regKey->GetChildName(index, childName); 1.320 + if (NS_SUCCEEDED(rv)) { 1.321 + verBlock curVer; 1.322 + TranslateVersionStr(childName.get(), &curVer); 1.323 + 1.324 + childName += NS_LITERAL_STRING("\\InstallPath"); 1.325 + 1.326 + nsCOMPtr<nsIWindowsRegKey> childKey; 1.327 + rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE, 1.328 + getter_AddRefs(childKey)); 1.329 + if (NS_SUCCEEDED(rv)) { 1.330 + // We have a sub key 1.331 + nsAutoString path; 1.332 + rv = childKey->ReadStringValue(NS_LITERAL_STRING(""), path); 1.333 + if (NS_SUCCEEDED(rv)) { 1.334 + if (CompareVersion(curVer, maxVer) >= 0 && 1.335 + CompareVersion(curVer, minVer) >= 0) { 1.336 + newestPath = path; 1.337 + CopyVersion(&maxVer, &curVer); 1.338 + } 1.339 + } 1.340 + } 1.341 + } 1.342 + } 1.343 + 1.344 + if (!newestPath.IsEmpty()) { 1.345 + newestPath += NS_LITERAL_STRING("\\browser"); 1.346 + rv = NS_NewLocalFile(newestPath, true, 1.347 + getter_AddRefs(localFile)); 1.348 + } 1.349 + } 1.350 + 1.351 + if (NS_FAILED(rv)) { 1.352 + return rv; 1.353 + } 1.354 + 1.355 + localFile.forget(_retval); 1.356 + return NS_OK; 1.357 +} 1.358 + 1.359 +nsresult 1.360 +nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator) 1.361 +{ 1.362 + NS_ENSURE_ARG_POINTER(aEnumerator); 1.363 + *aEnumerator = nullptr; 1.364 + 1.365 + nsCOMArray<nsIFile> dirs; 1.366 + 1.367 + GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs); 1.368 + GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs); 1.369 + 1.370 + return NS_NewArrayEnumerator(aEnumerator, dirs); 1.371 +} 1.372 + 1.373 +nsresult 1.374 +nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs) 1.375 +{ 1.376 + nsCOMPtr<nsIWindowsRegKey> regKey = 1.377 + do_CreateInstance("@mozilla.org/windows-registry-key;1"); 1.378 + NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE); 1.379 + 1.380 + nsresult rv = regKey->Open(aKey, 1.381 + NS_LITERAL_STRING("Software\\MozillaPlugins"), 1.382 + nsIWindowsRegKey::ACCESS_READ); 1.383 + if (NS_FAILED(rv)) { 1.384 + return rv; 1.385 + } 1.386 + 1.387 + uint32_t childCount = 0; 1.388 + regKey->GetChildCount(&childCount); 1.389 + 1.390 + for (uint32_t index = 0; index < childCount; ++index) { 1.391 + nsAutoString childName; 1.392 + rv = regKey->GetChildName(index, childName); 1.393 + if (NS_SUCCEEDED(rv)) { 1.394 + nsCOMPtr<nsIWindowsRegKey> childKey; 1.395 + rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE, 1.396 + getter_AddRefs(childKey)); 1.397 + if (NS_SUCCEEDED(rv) && childKey) { 1.398 + nsAutoString path; 1.399 + rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path); 1.400 + if (NS_SUCCEEDED(rv)) { 1.401 + nsCOMPtr<nsIFile> localFile; 1.402 + if (NS_SUCCEEDED(NS_NewLocalFile(path, true, 1.403 + getter_AddRefs(localFile))) && 1.404 + localFile) { 1.405 + // Some vendors use a path directly to the DLL so chop off 1.406 + // the filename 1.407 + bool isDir = false; 1.408 + if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) { 1.409 + nsCOMPtr<nsIFile> temp; 1.410 + localFile->GetParent(getter_AddRefs(temp)); 1.411 + if (temp) 1.412 + localFile = temp; 1.413 + } 1.414 + 1.415 + // Now we check to make sure it's actually on disk and 1.416 + // To see if we already have this directory in the array 1.417 + bool isFileThere = false; 1.418 + bool isDupEntry = false; 1.419 + if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) { 1.420 + int32_t c = aDirs.Count(); 1.421 + for (int32_t i = 0; i < c; i++) { 1.422 + nsIFile *dup = static_cast<nsIFile*>(aDirs[i]); 1.423 + if (dup && 1.424 + NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) && 1.425 + isDupEntry) { 1.426 + break; 1.427 + } 1.428 + } 1.429 + 1.430 + if (!isDupEntry) { 1.431 + aDirs.AppendObject(localFile); 1.432 + } 1.433 + } 1.434 + } 1.435 + } 1.436 + } 1.437 + } 1.438 + } 1.439 + return NS_OK; 1.440 +} 1.441 +