Bug 945192 - Add x64 support to loaddlls.cpp and general cleanup. r=bbondy, a=abillings
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 29 Jan 2015 11:50:33 -0800
changeset 243595 cf270a9a66ad
parent 243594 9ecb9e803a81
child 243596 992f411762d0
push id4406
push userryanvm@gmail.com
push date2015-01-29 21:23 +0000
treeherdermozilla-beta@cf270a9a66ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy, abillings
bugs945192
milestone36.0
Bug 945192 - Add x64 support to loaddlls.cpp and general cleanup. r=bbondy, a=abillings
toolkit/mozapps/update/updater/loaddlls.cpp
toolkit/mozapps/update/updater/moz.build
toolkit/mozapps/update/updater/updater.cpp
--- a/toolkit/mozapps/update/updater/loaddlls.cpp
+++ b/toolkit/mozapps/update/updater/loaddlls.cpp
@@ -11,25 +11,70 @@
 struct AutoLoadSystemDependencies
 {
   AutoLoadSystemDependencies()
   {
     // Remove the current directory from the search path for dynamically loaded
     // DLLs as a precaution.  This call has no effect for delay load DLLs.
     SetDllDirectory(L"");
 
-    // The order that these are loaded matter, for example if we load something
-    // that tries to load profapi.dll first, then profapi.dll would be loaded
-    // wrongly from the current directory.
-    static LPCWSTR delayDLLs[] = { L"profapi.dll", L"wsock32.dll",
-                                   L"crypt32.dll", L"cryptsp.dll",
-                                   L"cryptbase.dll", L"msasn1.dll",
-                                   L"userenv.dll", L"secur32.dll",
-                                   L"ws2_32.dll", L"ws2help.dll",
-                                   L"apphelp.dll", L"bcryptprimitives.dll" };
+    HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
+    if (module) {
+      // SetDefaultDllDirectories is always available on Windows 8 and above. It
+      // is also available on Windows Vista, Windows Server 2008, and
+      // Windows 7 when MS KB2533623 has been applied.
+      decltype(SetDefaultDllDirectories)* setDefaultDllDirectories =
+        (decltype(SetDefaultDllDirectories)*) GetProcAddress(module, "SetDefaultDllDirectories");
+      if (setDefaultDllDirectories) {
+        setDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
+        return;
+      }
+    }
+
+    // When SetDefaultDllDirectories is not available, fallback to preloading
+    // dlls. The order that these are loaded does not matter since they are
+    // loaded using the LOAD_WITH_ALTERED_SEARCH_PATH flag.
+#ifdef HAVE_64BIT_BUILD
+    // DLLs for Firefox x64 on Windows 7 (x64).
+    // Note: dwmapi.dll is preloaded since a crash will try to load it from the
+    // application's directory.
+    static LPCWSTR delayDLLs[] = { L"apphelp.dll",
+                                   L"cryptbase.dll",
+                                   L"cryptsp.dll",
+                                   L"dwmapi.dll",
+                                   L"mpr.dll",
+                                   L"ntmarta.dll",
+                                   L"profapi.dll",
+                                   L"propsys.dll",
+                                   L"sspicli.dll",
+                                   L"wsock32.dll" };
+
+#else
+    // DLLs for Firefox x86 on Windows XP through Windows 7 (x86 and x64).
+    // Note: dwmapi.dll is preloaded since a crash will try to load it from the
+    // application's directory.
+    static LPCWSTR delayDLLs[] = { L"apphelp.dll",
+                                   L"crypt32.dll",
+                                   L"cryptbase.dll",
+                                   L"cryptsp.dll",
+                                   L"dwmapi.dll",
+                                   L"mpr.dll",
+                                   L"msasn1.dll",
+                                   L"ntmarta.dll",
+                                   L"profapi.dll",
+                                   L"propsys.dll",
+                                   L"psapi.dll",
+                                   L"secur32.dll",
+                                   L"sspicli.dll",
+                                   L"userenv.dll",
+                                   L"uxtheme.dll",
+                                   L"ws2_32.dll",
+                                   L"ws2help.dll",
+                                   L"wsock32.dll" };
+#endif
 
     WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' };
     // If GetSystemDirectory fails we accept that we'll load the DLLs from the
     // normal search path.
     GetSystemDirectory(systemDirectory, MAX_PATH + 1);
     size_t systemDirLen = wcslen(systemDirectory);
 
     // Make the system directory path terminate with a slash
@@ -37,20 +82,22 @@ struct AutoLoadSystemDependencies
       systemDirectory[systemDirLen] = L'\\';
       ++systemDirLen;
       // No need to re-null terminate
     }
 
     // For each known DLL ensure it is loaded from the system32 directory
     for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) {
       size_t fileLen = wcslen(delayDLLs[i]);
-      wcsncpy(systemDirectory + systemDirLen, delayDLLs[i], 
+      wcsncpy(systemDirectory + systemDirLen, delayDLLs[i],
               MAX_PATH - systemDirLen);
       if (systemDirLen + fileLen <= MAX_PATH) {
         systemDirectory[systemDirLen + fileLen] = L'\0';
       } else {
         systemDirectory[MAX_PATH] = L'\0';
       }
       LPCWSTR fullModulePath = systemDirectory; // just for code readability
-      LoadLibraryW(fullModulePath);
+      // LOAD_WITH_ALTERED_SEARCH_PATH makes a dll look in its own directory for
+      // dependencies and is only available on Win 7 and below.
+      LoadLibraryExW(fullModulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
     }
   }
 } loadDLLs;
--- a/toolkit/mozapps/update/updater/moz.build
+++ b/toolkit/mozapps/update/updater/moz.build
@@ -95,16 +95,17 @@ for var in ('MAR_CHANNEL_ID', 'MOZ_APP_V
 
 LOCAL_INCLUDES += [
     '../common',
     '/xpcom/glue',
 ]
 
 DELAYLOAD_DLLS += [
     'crypt32.dll',
+    'comctl32.dll',
     'userenv.dll',
     'wsock32.dll',
 ]
 
 if CONFIG['_MSC_VER']:
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 elif CONFIG['OS_ARCH'] == 'WINNT':
     WIN32_EXE_LDFLAGS += ['-municode']
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2129,17 +2129,52 @@ UpdateThreadFunc(void *param)
     NS_tchar dataFile[MAXPATHLEN];
     rv = GetUpdateFileName(dataFile, sizeof(dataFile)/sizeof(dataFile[0]));
     if (rv == OK) {
       rv = gArchiveReader.Open(dataFile);
     }
 
 #ifdef MOZ_VERIFY_MAR_SIGNATURE
     if (rv == OK) {
+#ifdef XP_WIN
+      HKEY baseKey = nullptr;
+      wchar_t valueName[] = L"Image Path";
+      wchar_t rasenh[] = L"rsaenh.dll";
+      bool reset = false;
+      if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                        L"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Enhanced Cryptographic Provider v1.0",
+                        0, KEY_READ | KEY_WRITE,
+                        &baseKey) == ERROR_SUCCESS) {
+        wchar_t path[MAX_PATH + 1];
+        DWORD size = sizeof(path);
+        DWORD type;
+        if (RegQueryValueExW(baseKey, valueName, 0, &type,
+                             (LPBYTE)path, &size) == ERROR_SUCCESS) {
+          if (type == REG_SZ && wcscmp(path, rasenh) == 0) {
+            wchar_t rasenhFullPath[] = L"%SystemRoot%\\System32\\rsaenh.dll";
+            if (RegSetValueExW(baseKey, valueName, 0, REG_SZ,
+                               (const BYTE*)rasenhFullPath,
+                               sizeof(rasenhFullPath)) == ERROR_SUCCESS) {
+              reset = true;
+            }
+          }
+        }
+      }
+#endif
       rv = gArchiveReader.VerifySignature();
+#ifdef XP_WIN
+      if (baseKey) {
+        if (reset) {
+          RegSetValueExW(baseKey, valueName, 0, REG_SZ,
+                         (const BYTE*)rasenh,
+                         sizeof(rasenh));
+        }
+        RegCloseKey(baseKey);
+      }
+#endif
     }
 
     if (rv == OK) {
       if (rv == OK) {
         NS_tchar updateSettingsPath[MAX_TEXT_LEN];
         NS_tsnprintf(updateSettingsPath,
                      sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
                      NS_T("%s/update-settings.ini"), gWorkingDirPath);
@@ -2278,17 +2313,17 @@ int NS_main(int argc, NS_tchar **argv)
   // Our tests run with a different apply directory for each test.
   // We use this registry key on our test slaves to store the
   // allowed name/issuers.
   testOnlyFallbackKeyExists = DoesFallbackKeyExist();
 #endif
 
   // Remove everything except close window from the context menu
   {
-    HKEY hkApp;
+    HKEY hkApp = nullptr;
     RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Classes\\Applications",
                     0, nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr,
                     &hkApp, nullptr);
     RegCloseKey(hkApp);
     if (RegCreateKeyExW(HKEY_CURRENT_USER,
                         L"Software\\Classes\\Applications\\updater.exe",
                         0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr,
                         &hkApp, nullptr) == ERROR_SUCCESS) {
@@ -2518,17 +2553,17 @@ int NS_main(int argc, NS_tchar **argv)
       GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES;
 
     // If we're running from the service, then we were started with the same
     // token as the service so the permissions are already dropped.  If we're
     // running from an elevated updater that was started from an unelevated
     // updater, then we drop the permissions here. We do not drop the
     // permissions on the originally called updater because we use its token
     // to start the callback application.
-    if(startedFromUnelevatedUpdater) {
+    if (startedFromUnelevatedUpdater) {
       // Disable every privilege we don't need. Processes started using
       // CreateProcess will use the same token as this process.
       UACHelper::DisablePrivileges(nullptr);
     }
 
     if (updateLockFileHandle == INVALID_HANDLE_VALUE ||
         (useService && testOnlyFallbackKeyExists && noServiceFallback)) {
       if (!_waccess(elevatedLockFilePath, F_OK) &&
@@ -2578,17 +2613,17 @@ int NS_main(int argc, NS_tchar **argv)
         }
       }
 
       // Make sure the service registry entries for the instsallation path
       // are available.  If not don't use the service.
       if (useService) {
         WCHAR maintenanceServiceKey[MAX_PATH + 1];
         if (CalculateRegistryPathFromFilePath(gInstallDirPath, maintenanceServiceKey)) {
-          HKEY baseKey;
+          HKEY baseKey = nullptr;
           if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                             maintenanceServiceKey, 0,
                             KEY_READ | KEY_WOW64_64KEY,
                             &baseKey) == ERROR_SUCCESS) {
             RegCloseKey(baseKey);
           } else {
             useService = testOnlyFallbackKeyExists;
             if (!useService) {