Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsPluginDirServiceProvider.h"
8 #include "nsCRT.h"
9 #include "nsIFile.h"
10 #include "nsDependentString.h"
11 #include "nsArrayEnumerator.h"
12 #include "mozilla/Preferences.h"
14 #include <windows.h>
15 #include "nsIWindowsRegKey.h"
17 using namespace mozilla;
19 typedef struct structVer
20 {
21 WORD wMajor;
22 WORD wMinor;
23 WORD wRelease;
24 WORD wBuild;
25 } verBlock;
27 static void
28 ClearVersion(verBlock *ver)
29 {
30 ver->wMajor = 0;
31 ver->wMinor = 0;
32 ver->wRelease = 0;
33 ver->wBuild = 0;
34 }
36 static BOOL
37 FileExists(LPCWSTR szFile)
38 {
39 return GetFileAttributesW(szFile) != 0xFFFFFFFF;
40 }
42 // Get file version information from a file
43 static BOOL
44 GetFileVersion(LPCWSTR szFile, verBlock *vbVersion)
45 {
46 UINT uLen;
47 UINT dwLen;
48 BOOL bRv;
49 DWORD dwHandle;
50 LPVOID lpData;
51 LPVOID lpBuffer;
52 VS_FIXEDFILEINFO *lpBuffer2;
54 ClearVersion(vbVersion);
55 if (FileExists(szFile)) {
56 bRv = TRUE;
57 LPCWSTR lpFilepath = szFile;
58 dwLen = GetFileVersionInfoSizeW(lpFilepath, &dwHandle);
59 lpData = (LPVOID)malloc(dwLen);
60 uLen = 0;
62 if (lpData && GetFileVersionInfoW(lpFilepath, dwHandle, dwLen, lpData) != 0) {
63 if (VerQueryValueW(lpData, L"\\", &lpBuffer, &uLen) != 0) {
64 lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
66 vbVersion->wMajor = HIWORD(lpBuffer2->dwFileVersionMS);
67 vbVersion->wMinor = LOWORD(lpBuffer2->dwFileVersionMS);
68 vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS);
69 vbVersion->wBuild = LOWORD(lpBuffer2->dwFileVersionLS);
70 }
71 }
73 free(lpData);
74 } else {
75 /* File does not exist */
76 bRv = FALSE;
77 }
79 return bRv;
80 }
82 // Will deep copy ver2 into ver1
83 static void
84 CopyVersion(verBlock *ver1, verBlock *ver2)
85 {
86 ver1->wMajor = ver2->wMajor;
87 ver1->wMinor = ver2->wMinor;
88 ver1->wRelease = ver2->wRelease;
89 ver1->wBuild = ver2->wBuild;
90 }
92 // Convert a string version to a version struct
93 static void
94 TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion)
95 {
96 WCHAR* szNum1 = nullptr;
97 WCHAR* szNum2 = nullptr;
98 WCHAR* szNum3 = nullptr;
99 WCHAR* szNum4 = nullptr;
100 WCHAR* szJavaBuild = nullptr;
102 WCHAR *strVer = nullptr;
103 if (szVersion) {
104 strVer = wcsdup(szVersion);
105 }
107 if (!strVer) {
108 // Out of memory
109 ClearVersion(vbVersion);
110 return;
111 }
113 // Java may be using an underscore instead of a dot for the build ID
114 szJavaBuild = wcschr(strVer, '_');
115 if (szJavaBuild) {
116 szJavaBuild[0] = '.';
117 }
119 szNum1 = wcstok(strVer, L".");
120 szNum2 = wcstok(nullptr, L".");
121 szNum3 = wcstok(nullptr, L".");
122 szNum4 = wcstok(nullptr, L".");
124 vbVersion->wMajor = szNum1 ? (WORD) _wtoi(szNum1) : 0;
125 vbVersion->wMinor = szNum2 ? (WORD) _wtoi(szNum2) : 0;
126 vbVersion->wRelease = szNum3 ? (WORD) _wtoi(szNum3) : 0;
127 vbVersion->wBuild = szNum4 ? (WORD) _wtoi(szNum4) : 0;
129 free(strVer);
130 }
132 // Compare two version struct, return zero if the same
133 static int
134 CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
135 {
136 if (vbVersionOld.wMajor > vbVersionNew.wMajor) {
137 return 4;
138 } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) {
139 return -4;
140 }
142 if (vbVersionOld.wMinor > vbVersionNew.wMinor) {
143 return 3;
144 } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) {
145 return -3;
146 }
148 if (vbVersionOld.wRelease > vbVersionNew.wRelease) {
149 return 2;
150 } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) {
151 return -2;
152 }
154 if (vbVersionOld.wBuild > vbVersionNew.wBuild) {
155 return 1;
156 } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) {
157 return -1;
158 }
160 /* the versions are all the same */
161 return 0;
162 }
164 //*****************************************************************************
165 // nsPluginDirServiceProvider::Constructor/Destructor
166 //*****************************************************************************
168 nsPluginDirServiceProvider::nsPluginDirServiceProvider()
169 {
170 }
172 nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
173 {
174 }
176 //*****************************************************************************
177 // nsPluginDirServiceProvider::nsISupports
178 //*****************************************************************************
180 NS_IMPL_ISUPPORTS(nsPluginDirServiceProvider,
181 nsIDirectoryServiceProvider)
183 //*****************************************************************************
184 // nsPluginDirServiceProvider::nsIDirectoryServiceProvider
185 //*****************************************************************************
187 NS_IMETHODIMP
188 nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant,
189 nsIFile **_retval)
190 {
191 nsCOMPtr<nsIFile> localFile;
192 nsresult rv = NS_ERROR_FAILURE;
194 NS_ENSURE_ARG(charProp);
196 *_retval = nullptr;
197 *persistant = false;
199 nsCOMPtr<nsIWindowsRegKey> regKey =
200 do_CreateInstance("@mozilla.org/windows-registry-key;1");
201 NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
203 if (nsCRT::strcmp(charProp, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
204 nsAdoptingCString strVer = Preferences::GetCString(charProp);
205 if (!strVer) {
206 return NS_ERROR_FAILURE;
207 }
208 verBlock minVer;
209 TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
211 // Look for the Quicktime system installation plugins directory
212 verBlock qtVer;
213 ClearVersion(&qtVer);
215 // First we need to check the version of Quicktime via checking
216 // the EXE's version table
217 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
218 NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe"),
219 nsIWindowsRegKey::ACCESS_READ);
220 if (NS_SUCCEEDED(rv)) {
221 nsAutoString path;
222 rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
223 if (NS_SUCCEEDED(rv)) {
224 GetFileVersion(path.get(), &qtVer);
225 }
226 regKey->Close();
227 }
228 if (CompareVersion(qtVer, minVer) < 0)
229 return rv;
231 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
232 NS_LITERAL_STRING("software\\Apple Computer, Inc.\\QuickTime"),
233 nsIWindowsRegKey::ACCESS_READ);
234 if (NS_SUCCEEDED(rv)) {
235 nsAutoString path;
236 rv = regKey->ReadStringValue(NS_LITERAL_STRING("InstallDir"), path);
237 if (NS_SUCCEEDED(rv)) {
238 path += NS_LITERAL_STRING("\\Plugins");
239 rv = NS_NewLocalFile(path, true,
240 getter_AddRefs(localFile));
241 }
242 }
243 } else if (nsCRT::strcmp(charProp, NS_WIN_WMP_SCAN_KEY) == 0) {
244 nsAdoptingCString strVer = Preferences::GetCString(charProp);
245 if (!strVer) {
246 return NS_ERROR_FAILURE;
247 }
248 verBlock minVer;
249 TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
251 // Look for Windows Media Player system installation plugins directory
252 verBlock wmpVer;
253 ClearVersion(&wmpVer);
255 // First we need to check the version of WMP
256 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
257 NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe"),
258 nsIWindowsRegKey::ACCESS_READ);
259 if (NS_SUCCEEDED(rv)) {
260 nsAutoString path;
261 rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
262 if (NS_SUCCEEDED(rv)) {
263 GetFileVersion(path.get(), &wmpVer);
264 }
265 regKey->Close();
266 }
267 if (CompareVersion(wmpVer, minVer) < 0)
268 return rv;
270 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
271 NS_LITERAL_STRING("software\\Microsoft\\MediaPlayer"),
272 nsIWindowsRegKey::ACCESS_READ);
273 if (NS_SUCCEEDED(rv)) {
274 nsAutoString path;
275 rv = regKey->ReadStringValue(NS_LITERAL_STRING("Installation Directory"),
276 path);
277 if (NS_SUCCEEDED(rv)) {
278 rv = NS_NewLocalFile(path, true,
279 getter_AddRefs(localFile));
280 }
281 }
282 } else if (nsCRT::strcmp(charProp, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
283 nsAdoptingCString strVer = Preferences::GetCString(charProp);
284 if (!strVer) {
285 return NS_ERROR_FAILURE;
286 }
288 verBlock minVer;
289 TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
291 // Look for Adobe Acrobat system installation plugins directory
292 verBlock maxVer;
293 ClearVersion(&maxVer);
295 nsAutoString newestPath;
297 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
298 NS_LITERAL_STRING("software\\Adobe\\Acrobat Reader"),
299 nsIWindowsRegKey::ACCESS_READ);
300 if (NS_FAILED(rv)) {
301 rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
302 NS_LITERAL_STRING("software\\Adobe\\Adobe Acrobat"),
303 nsIWindowsRegKey::ACCESS_READ);
304 if (NS_FAILED(rv)) {
305 return NS_ERROR_FAILURE;
306 }
307 }
309 // We must enumerate through the keys because what if there is
310 // more than one version?
311 uint32_t childCount = 0;
312 regKey->GetChildCount(&childCount);
314 for (uint32_t index = 0; index < childCount; ++index) {
315 nsAutoString childName;
316 rv = regKey->GetChildName(index, childName);
317 if (NS_SUCCEEDED(rv)) {
318 verBlock curVer;
319 TranslateVersionStr(childName.get(), &curVer);
321 childName += NS_LITERAL_STRING("\\InstallPath");
323 nsCOMPtr<nsIWindowsRegKey> childKey;
324 rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
325 getter_AddRefs(childKey));
326 if (NS_SUCCEEDED(rv)) {
327 // We have a sub key
328 nsAutoString path;
329 rv = childKey->ReadStringValue(NS_LITERAL_STRING(""), path);
330 if (NS_SUCCEEDED(rv)) {
331 if (CompareVersion(curVer, maxVer) >= 0 &&
332 CompareVersion(curVer, minVer) >= 0) {
333 newestPath = path;
334 CopyVersion(&maxVer, &curVer);
335 }
336 }
337 }
338 }
339 }
341 if (!newestPath.IsEmpty()) {
342 newestPath += NS_LITERAL_STRING("\\browser");
343 rv = NS_NewLocalFile(newestPath, true,
344 getter_AddRefs(localFile));
345 }
346 }
348 if (NS_FAILED(rv)) {
349 return rv;
350 }
352 localFile.forget(_retval);
353 return NS_OK;
354 }
356 nsresult
357 nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
358 {
359 NS_ENSURE_ARG_POINTER(aEnumerator);
360 *aEnumerator = nullptr;
362 nsCOMArray<nsIFile> dirs;
364 GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
365 GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
367 return NS_NewArrayEnumerator(aEnumerator, dirs);
368 }
370 nsresult
371 nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs)
372 {
373 nsCOMPtr<nsIWindowsRegKey> regKey =
374 do_CreateInstance("@mozilla.org/windows-registry-key;1");
375 NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
377 nsresult rv = regKey->Open(aKey,
378 NS_LITERAL_STRING("Software\\MozillaPlugins"),
379 nsIWindowsRegKey::ACCESS_READ);
380 if (NS_FAILED(rv)) {
381 return rv;
382 }
384 uint32_t childCount = 0;
385 regKey->GetChildCount(&childCount);
387 for (uint32_t index = 0; index < childCount; ++index) {
388 nsAutoString childName;
389 rv = regKey->GetChildName(index, childName);
390 if (NS_SUCCEEDED(rv)) {
391 nsCOMPtr<nsIWindowsRegKey> childKey;
392 rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
393 getter_AddRefs(childKey));
394 if (NS_SUCCEEDED(rv) && childKey) {
395 nsAutoString path;
396 rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path);
397 if (NS_SUCCEEDED(rv)) {
398 nsCOMPtr<nsIFile> localFile;
399 if (NS_SUCCEEDED(NS_NewLocalFile(path, true,
400 getter_AddRefs(localFile))) &&
401 localFile) {
402 // Some vendors use a path directly to the DLL so chop off
403 // the filename
404 bool isDir = false;
405 if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
406 nsCOMPtr<nsIFile> temp;
407 localFile->GetParent(getter_AddRefs(temp));
408 if (temp)
409 localFile = temp;
410 }
412 // Now we check to make sure it's actually on disk and
413 // To see if we already have this directory in the array
414 bool isFileThere = false;
415 bool isDupEntry = false;
416 if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
417 int32_t c = aDirs.Count();
418 for (int32_t i = 0; i < c; i++) {
419 nsIFile *dup = static_cast<nsIFile*>(aDirs[i]);
420 if (dup &&
421 NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
422 isDupEntry) {
423 break;
424 }
425 }
427 if (!isDupEntry) {
428 aDirs.AppendObject(localFile);
429 }
430 }
431 }
432 }
433 }
434 }
435 }
436 return NS_OK;
437 }