diff --git a/application/basilisk/installer/Makefile.in b/application/basilisk/installer/Makefile.in
index 80977549f..882a1e214 100644
--- a/application/basilisk/installer/Makefile.in
+++ b/application/basilisk/installer/Makefile.in
@@ -57,6 +57,9 @@ DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER)
 ifdef MOZ_D3DCOMPILER_VISTA_DLL
 DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL)
 endif
+ifdef MOZ_D3DCOMPILER_XP_DLL
+DEFINES += -DMOZ_D3DCOMPILER_XP_DLL=$(MOZ_D3DCOMPILER_XP_DLL)
+endif
 endif
 
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
diff --git a/application/basilisk/installer/windows/nsis/defines.nsi.in b/application/basilisk/installer/windows/nsis/defines.nsi.in
index 5e9f0ae27..b72d93aa5 100644
--- a/application/basilisk/installer/windows/nsis/defines.nsi.in
+++ b/application/basilisk/installer/windows/nsis/defines.nsi.in
@@ -68,9 +68,9 @@
 #ifdef HAVE_64BIT_BUILD
 !define HAVE_64BIT_BUILD
 !define ARCH "x64"
-!define MinSupportedVer "Microsoft Windows 7 x64"
+!define MinSupportedVer "Microsoft Windows XP x64"
 #else
-!define MinSupportedVer "Microsoft Windows 7"
+!define MinSupportedVer "Microsoft Windows XP"
 !define ARCH "x86"
 #endif
 
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
index 0394b352b..da63a55ca 100755
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -9,6 +9,10 @@ ifdef MOZ_D3DCOMPILER_VISTA_DLL_PATH
 	cp -fp "$(MOZ_D3DCOMPILER_VISTA_DLL_PATH)" "$(DIST)/bin"
 endif
 
+ifdef MOZ_D3DCOMPILER_XP_CAB
+	expand '$(MOZ_D3DCOMPILER_XP_CAB)' -F:$(MOZ_D3DCOMPILER_XP_DLL) '$(DIST)/bin'
+endif
+
 endif
 
 include $(topsrcdir)/config/rules.mk
diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp
index 41060a38b..84f30a57f 100644
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -321,6 +321,11 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
             if (LoadLibrarySystem32(L"d3dcompiler_47.dll"))
                 break;
 
+#ifdef MOZ_D3DCOMPILER_XP_DLL
+            if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL))))
+                break;
+#endif
+
 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
             if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
                 break;
diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
index 6f43a495d..596612bb8 100644
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -150,6 +150,8 @@ FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
     DEFINES['MOZ_D3DCOMPILER_VISTA_DLL'] = CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']
+if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
+    DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
index f51ff82d2..6a978f8c3 100755
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1686,10 +1686,10 @@ gfxWindowsPlatform::InitGPUProcessSupport()
 bool
 gfxWindowsPlatform::DwmCompositionEnabled()
 {
-  MOZ_ASSERT(WinUtils::dwmIsCompositionEnabledPtr);
+//  MOZ_ASSERT(WinUtils::dwmIsCompositionEnabledPtr);
   BOOL dwmEnabled = false;
 
-  if (FAILED(WinUtils::dwmIsCompositionEnabledPtr(&dwmEnabled))) {
+  if (!WinUtils::dwmIsCompositionEnabledPtr || FAILED(WinUtils::dwmIsCompositionEnabledPtr(&dwmEnabled))) {
     return false;
   }
 
diff --git a/ipc/mscom/MainThreadRuntime.cpp b/ipc/mscom/MainThreadRuntime.cpp
index 7bd8e0049..7f25c4ca0 100644
--- a/ipc/mscom/MainThreadRuntime.cpp
+++ b/ipc/mscom/MainThreadRuntime.cpp
@@ -65,7 +65,7 @@ MainThreadRuntime::MainThreadRuntime()
   // Disable COM's catch-all exception handler
   mInitResult = globalOpts->Set(COMGLB_EXCEPTION_HANDLING,
                                 COMGLB_EXCEPTION_DONOT_HANDLE_ANY);
-  MOZ_ASSERT(SUCCEEDED(mInitResult));
+  //MOZ_ASSERT(SUCCEEDED(mInitResult));
 
   // Disable the BSTR cache (as it never invalidates, thus leaking memory)
   ::SetOaNoCache();
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 59e9a381e..db94a9eab 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -210,7 +210,7 @@ FlagAllOperandsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block)
         if (MResumePoint* rp = ins->resumePoint()) {
             // Note: no need to iterate over the caller's of the resume point as
             // this is the same as the entry resume point.
-            MOZ_ASSERT(&rp->block()->info() == &info);
+            //MOZ_ASSERT(&rp->block()->info() == &info);
             for (size_t i = 0, e = rp->numOperands(); i < e; i++) {
                 if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses inner loop"))
                     return false;
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index b6be89e9f..17b684dbf 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -6560,8 +6560,8 @@ js::gc::CheckHashTablesAfterMovingGC(JSRuntime* rt)
         c->dtoaCache.checkCacheAfterMovingGC();
         c->checkWrapperMapAfterMovingGC();
         c->checkScriptMapsAfterMovingGC();
-        if (c->debugEnvs)
-            c->debugEnvs->checkHashTablesAfterMovingGC(rt);
+        /*if (c->debugEnvs)
+            c->debugEnvs->checkHashTablesAfterMovingGC(rt);*/
     }
 }
 #endif
diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp
index faf61655c..e3322205a 100644
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -2389,7 +2389,7 @@ DebugEnvironments::finish()
     proxiedEnvs.clear();
 }
 
-#ifdef JSGC_HASH_TABLE_CHECKS
+#if 0//def JSGC_HASH_TABLE_CHECKS
 void
 DebugEnvironments::checkHashTablesAfterMovingGC(JSRuntime* runtime)
 {
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index e0c5e46ca..dde44622d 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5079,9 +5079,9 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis              aAxis,
   NS_PRECONDITION(aFrame->GetParent(),
                   "IntrinsicForAxis called on frame not in tree");
   NS_PRECONDITION(aType == MIN_ISIZE || aType == PREF_ISIZE, "bad type");
-  MOZ_ASSERT(aFrame->GetParent()->Type() != LayoutFrameType::GridContainer ||
+  /*MOZ_ASSERT(aFrame->GetParent()->Type() != LayoutFrameType::GridContainer ||
              aPercentageBasis.isSome(),
-             "grid layout should always pass a percentage basis");
+             "grid layout should always pass a percentage basis");*/
 
   const bool horizontalAxis = MOZ_LIKELY(aAxis == eAxisHorizontal);
 #ifdef DEBUG_INTRINSIC_WIDTH
diff --git a/mfbt/WindowsVersion.h b/mfbt/WindowsVersion.h
index 4156f4f64..5fa30c5c1 100644
--- a/mfbt/WindowsVersion.h
+++ b/mfbt/WindowsVersion.h
@@ -84,7 +84,7 @@ IsWindowsBuildOrLater(uint32_t aBuild)
   return false;
 }
 
-#if defined(_M_X64) || defined(_M_AMD64)
+#if 0//defined(_M_X64) || defined(_M_AMD64)
 // We support only Win7 or later on Win64.
 MOZ_ALWAYS_INLINE bool
 IsXPSP3OrLater()
diff --git a/old-configure.in b/old-configure.in
index 800f154b3..441fdf368 100644
--- a/old-configure.in
+++ b/old-configure.in
@@ -987,7 +987,10 @@ case "$target" in
         IMPORT_LIB_SUFFIX=lib
         MKSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKCSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        WIN32_SUBSYSTEM_VERSION=6.01
+        WIN32_SUBSYSTEM_VERSION=5.01
+        if test "$HAVE_64BIT_BUILD"; then
+            WIN32_SUBSYSTEM_VERSION=5.02
+        fi
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
@@ -3336,6 +3339,9 @@ MOZ_D3D_CPU_SUFFIX=
 MOZ_HAS_WINSDK_WITH_D3D=
 MOZ_D3DCOMPILER_VISTA_DLL=
 MOZ_D3DCOMPILER_VISTA_DLL_PATH=
+MOZ_DIRECTX_SDK_PATH=
+MOZ_D3DCOMPILER_XP_DLL=
+MOZ_D3DCOMPILER_XP_CAB=
 
 if test "$COMPILE_ENVIRONMENT" ; then
 case "$target_os" in
@@ -3361,6 +3367,8 @@ if test -n "$MOZ_WEBGL_CONFORMANT"; then
   AC_DEFINE(MOZ_WEBGL_CONFORMANT)
 fi
 
+MOZ_REQUIRE_ALL_D3DCS=1
+
 dnl ========================================================
 dnl D3D compiler DLL
 dnl ========================================================
@@ -3411,19 +3419,85 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
     MOZ_CHECK_HEADER(d3d10.h, MOZ_HAS_WINSDK_WITH_D3D=1)
   fi
 
+  ######################################
+  # Find _43 for use by XP.
+
+    # Get the SDK path from the registry.
+    # First try to get the June 2010 SDK
+    MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK (June 2010)' | head -n 1`
+    if test -z "$MOZ_DIRECTX_SDK_REG_KEY" ; then
+      # Otherwise just take whatever comes first
+      MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK' | head -n 1`
+    fi
+    MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/' | sed 's,\\\\,/,g'`
+
+    if test -n "$MOZ_DIRECTX_SDK_PATH" &&
+       test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_D3D_CPU_SUFFIX/dxguid.lib ; then
+      AC_MSG_RESULT([Found DirectX SDK via registry, using $MOZ_DIRECTX_SDK_PATH])
+    else
+      AC_MSG_RESULT([DirectX SDK not found.])
+      MOZ_DIRECTX_SDK_PATH=
+    fi
+
+    # Check that our DirectX SDK is acceptable.
+    if test -n "$MOZ_DIRECTX_SDK_PATH"; then
+      if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
+        AC_MSG_RESULT([Found the February 2010 DirectX SDK, which is unacceptable to ANGLE.])
+        MOZ_DIRECTX_SDK_PATH=
+      fi
+    fi
+
+    if test -n "$MOZ_DIRECTX_SDK_PATH"; then
+      # Find a D3D compiler DLL in the DirectX SDK, if we didn't find one already.
+      # Get the SDK numeric version (e.g. 43) by looking at the dependencies of d3dx9.lib
+      MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_D3D_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'`
+
+      if test -n "$MOZ_D3DX9_VERSION" ; then
+        MOZ_D3DCOMPILER_XP_CAB=`find "$MOZ_DIRECTX_SDK_PATH"/Redist -name *D3DCompiler_${MOZ_D3DX9_VERSION}_${MOZ_D3D_CPU_SUFFIX}.cab | head -n1`
+
+        if test -n "$MOZ_D3DCOMPILER_XP_CAB"; then
+          MOZ_D3DCOMPILER_XP_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
+        else
+          AC_MSG_RESULT([Couldn't find a CAB containing the D3D compiler DLL.])
+          AC_MSG_ERROR([DirectX SDK at "$MOZ_DIRECTX_SDK_PATH" appears broken.])
+          MOZ_DIRECTX_SDK_PATH=
+        fi
+      else
+        AC_MSG_RESULT([Couldn't determine the D3DX9 version for the DirectX SDK.])
+        MOZ_DIRECTX_SDK_PATH=
+      fi
+    else
+      AC_MSG_RESULT([Couldn't find an acceptable DirectX SDK for ANGLE, needed for d3dcompiler_43.])
+    fi
+
   ######################################
   # Check that we found what we needed.
   MOZ_FOUND_A_D3D_COMPILER=
+  MOZ_FOUND_BOTH_D3D_COMPILERS=1
 
   if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then
     MOZ_FOUND_A_D3D_COMPILER=1
     AC_MSG_RESULT([Found d3dcompiler DLL for Vista+: $MOZ_D3DCOMPILER_VISTA_DLL])
+  else
+    MOZ_FOUND_BOTH_D3D_COMPILERS=
+  fi
+
+  if test -n "$MOZ_D3DCOMPILER_XP_DLL"; then
+    MOZ_FOUND_A_D3D_COMPILER=1
+    AC_MSG_RESULT([Found d3dcompiler DLL for XP: $MOZ_D3DCOMPILER_XP_DLL])
+  else
+    MOZ_FOUND_BOTH_D3D_COMPILERS=
   fi
 
   if test -z "$CROSS_COMPILE"; then
     if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
       AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
     fi
+
+    if test -n "$MOZ_REQUIRE_ALL_D3DCS" -a -z "$MOZ_FOUND_BOTH_D3D_COMPILERS"; then
+      AC_MSG_ERROR([Both D3D compilers _43 and _46+ are required by --enable-require-d3d-compilers.])
+      AC_MSG_ERROR([  Install Windows SDK 8.0+, as well as DirectX SDK (June 2010 version or newer), or reconfigure without this flag.])
+    fi
   fi
 fi # MOZ_ANGLE_RENDERER
 
@@ -5220,6 +5294,9 @@ AC_SUBST(MOZ_D3D_CPU_SUFFIX)
 AC_SUBST(MOZ_HAS_WINSDK_WITH_D3D)
 AC_SUBST(MOZ_D3DCOMPILER_VISTA_DLL)
 AC_SUBST(MOZ_D3DCOMPILER_VISTA_DLL_PATH)
+AC_SUBST(MOZ_DIRECTX_SDK_PATH)
+AC_SUBST(MOZ_D3DCOMPILER_XP_DLL)
+AC_SUBST(MOZ_D3DCOMPILER_XP_CAB)
 
 AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
 AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)
diff --git a/security/certverifier/ExtendedValidation.cpp b/security/certverifier/ExtendedValidation.cpp
index 056c28e32..4efdb3f24 100644
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -1268,7 +1268,7 @@ LoadExtendedValidationInfo()
     nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];
 
     SECStatus srv;
-#ifdef DEBUG
+#if 0//def DEBUG
     // This section of code double-checks that we calculated the correct
     // certificate hash given the issuer and serial number and that it is
     // actually present in our loaded root certificates module. It is
diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh
index df0f3fbc6..27bb62790 100755
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -4949,7 +4949,7 @@
       ${EndIf}
 
       ; Windows NT 6.0 (Vista/Server 2008) and lower are not supported.
-      ${Unless} ${AtLeastWin7}
+      ${Unless} ${AtLeastWinXP}
         MessageBox MB_OK|MB_ICONSTOP "$R9"
         ; Nothing initialized so no need to call OnEndCommon
         Quit
diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp
index d52bdb1f4..ec2877225 100644
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -235,6 +235,9 @@ ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
 enum {
   kWindowsUnknown = 0,
+  kWindowsXP = 0x50001,
+  kWindowsServer2003 = 0x50002,
+  kWindowsVista = 0x60000,
   kWindows7 = 0x60001,
   kWindows8 = 0x60002,
   kWindows8_1 = 0x60003,
@@ -761,6 +764,10 @@ static OperatingSystem
 WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
 {
   switch(aWindowsVersion) {
+    case kWindowsXP:
+      return OperatingSystem::WindowsXP;
+    case kWindowsServer2003:
+      return OperatingSystem::WindowsServer2003;
     case kWindows7:
       return OperatingSystem::Windows7;
     case kWindows8:
@@ -914,6 +921,22 @@ GfxInfo::GetGfxDriverInfo()
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMAX3000, 1930, "FEATURE_FAILURE_594877_11");
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelHDGraphicsToSandyBridge, 2202, "FEATURE_FAILURE_594877_12");
 
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA500,   V(3,0,20,3200), "FEATURE_FAILURE_INTEL_XP_1");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA900,   V(6,14,10,4764), "FEATURE_FAILURE_INTEL_XP_2");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA950,   V(6,14,10,4926), "FEATURE_FAILURE_INTEL_XP_3");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA3150,  V(6,14,10,5134), "FEATURE_FAILURE_INTEL_XP_4");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX3000, V(6,14,10,5218), "FEATURE_FAILURE_INTEL_XP_5");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX4500HD, V(6,14,10,4969), "FEATURE_FAILURE_INTEL_XP_6");
+
+    // StrechRect seems to suffer from precision issues which leads to artifacting
+    // during content drawing starting with at least version 6.14.10.5082
+    // and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info.
+    APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsXP,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel),
+      (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "FEATURE_FAILURE_INTEL_XP_7", "6.14.10.5218");
+
     /* Disable Direct2D on Intel GMAX4500 devices because of rendering corruption discovered
      * in bug 1180379. These seems to affect even the most recent drivers. We're black listing
      * all of the devices to be safe even though we've only confirmed the issue on the G45
@@ -1176,6 +1199,23 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
       return NS_OK;
     }
 
+    // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
+    // whitelist them, actually we do know that this combination of device and driver version
+    // works well.
+    if (mWindowsVersion == kWindowsXP &&
+        adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
+        adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
+        driverVersion == V(6,14,11,7756))
+    {
+      *aStatus = FEATURE_STATUS_OK;
+      return NS_OK;
+    }
+
+    // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
+    // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
+    if (os == OperatingSystem::WindowsServer2003)
+      os = OperatingSystem::WindowsXP;
+
     if (mHasDriverVersionMismatch) {
       *aStatus = nsIGfxInfo::FEATURE_BLOCKED_MISMATCHED_VERSION;
       return NS_OK;
diff --git a/widget/windows/WindowsUIUtils.cpp b/widget/windows/WindowsUIUtils.cpp
index 223511859..a3285679a 100644
--- a/widget/windows/WindowsUIUtils.cpp
+++ b/widget/windows/WindowsUIUtils.cpp
@@ -22,7 +22,7 @@
 #include "nsIWidget.h"
 
 /* mingw currently doesn't support windows.ui.viewmanagement.h, so we disable it until it's fixed. */
-#ifndef __MINGW32__
+#if 0 //ndef __MINGW32__
 
 #include <windows.ui.viewmanagement.h>
 
@@ -119,7 +119,7 @@ WindowsUIUtils::GetInTabletMode(bool* aResult)
 NS_IMETHODIMP
 WindowsUIUtils::UpdateTabletModeState()
 {
-#ifndef __MINGW32__
+#if 0//ndef __MINGW32__
   if (!IsWin10OrLater()) {
     return NS_OK;
   }
diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp
index 4f2aa5ccc..cc19f6cbc 100644
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -28,6 +28,7 @@
 #include "nsPIDOMWindow.h"
 #include "GoannaProfiler.h"
 
+using mozilla::IsVistaOrLater;
 using mozilla::IsWin8OrLater;
 using mozilla::MakeUnique;
 using mozilla::mscom::EnsureMTA;
@@ -218,6 +219,191 @@ STDMETHODIMP nsFilePicker::QueryInterface(REFIID refiid, void** ppvResult)
   return E_NOINTERFACE;
 }
 
+/*
+ * XP picker callbacks
+ */
+
+// Show - Display the file dialog
+int CALLBACK
+BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
+{
+  if (uMsg == BFFM_INITIALIZED)
+  {
+    char16_t * filePath = (char16_t *) lpData;
+    if (filePath)
+      ::SendMessageW(hwnd, BFFM_SETSELECTIONW,
+                     TRUE /* true because lpData is a path string */,
+                     lpData);
+  }
+  return 0;
+}
+
+static void
+EnsureWindowVisible(HWND hwnd) 
+{
+  // Obtain the monitor which has the largest area of intersection 
+  // with the window, or nullptr if there is no intersection.
+  HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
+  if (!monitor) {
+    // The window is not visible, we should reposition it to the same place as its parent
+    HWND parentHwnd = GetParent(hwnd);
+    RECT parentRect;
+    GetWindowRect(parentHwnd, &parentRect);
+    SetWindowPos(hwnd, nullptr, parentRect.left, parentRect.top, 0, 0,
+                 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+  }
+}
+
+// Callback hook which will ensure that the window is visible. Currently
+// only in use on os <= XP.
+UINT_PTR CALLBACK
+nsFilePicker::FilePickerHook(HWND hwnd,
+                             UINT msg,
+                             WPARAM wParam,
+                             LPARAM lParam) 
+{
+  switch(msg) {
+    case WM_NOTIFY:
+      {
+        LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
+        if (!lpofn || !lpofn->lpOFN) {
+          return 0;
+        }
+        
+        if (CDN_INITDONE == lpofn->hdr.code) {
+          // The Window will be automatically moved to the last position after
+          // CDN_INITDONE.  We post a message to ensure the window will be visible
+          // so it will be done after the automatic last position window move.
+          PostMessage(hwnd, MOZ_WM_ENSUREVISIBLE, 0, 0);
+        }
+      }
+      break;
+    case MOZ_WM_ENSUREVISIBLE:
+      EnsureWindowVisible(GetParent(hwnd));
+      break;
+    case WM_INITDIALOG:
+      {
+        OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
+        SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
+        nsFilePicker* picker = reinterpret_cast<nsFilePicker*>(pofn->lCustData);
+        if (picker) {
+          picker->SetDialogHandle(hwnd);
+          SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
+        }
+      }
+      break;
+    case WM_TIMER:
+      {
+        // Check to see if our parent has been torn down, if so, we close too.
+        if (wParam == kDialogTimerID) {
+          nsFilePicker* picker = 
+            reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
+          if (picker && picker->ClosePickerIfNeeded(true)) {
+            KillTimer(hwnd, kDialogTimerID);
+          }
+        }
+      }
+      break;
+  }
+  return 0;
+}
+
+
+// Callback hook which will dynamically allocate a buffer large enough
+// for the file picker dialog.  Currently only in use on  os <= XP.
+UINT_PTR CALLBACK
+nsFilePicker::MultiFilePickerHook(HWND hwnd,
+                                  UINT msg,
+                                  WPARAM wParam,
+                                  LPARAM lParam)
+{
+  switch (msg) {
+    case WM_INITDIALOG:
+      {
+        // Finds the child drop down of a File Picker dialog and sets the 
+        // maximum amount of text it can hold when typed in manually.
+        // A wParam of 0 mean 0x7FFFFFFE characters.
+        HWND comboBox = FindWindowEx(GetParent(hwnd), nullptr, 
+                                     L"ComboBoxEx32", nullptr );
+        if(comboBox)
+          SendMessage(comboBox, CB_LIMITTEXT, 0, 0);
+        // Store our nsFilePicker ptr for future use
+        OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
+        SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
+        nsFilePicker* picker =
+          reinterpret_cast<nsFilePicker*>(pofn->lCustData);
+        if (picker) {
+          picker->SetDialogHandle(hwnd);
+          SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
+        }
+      }
+      break;
+    case WM_NOTIFY:
+      {
+        LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
+        if (!lpofn || !lpofn->lpOFN) {
+          return 0;
+        }
+        // CDN_SELCHANGE is sent when the selection in the list box of the file
+        // selection dialog changes
+        if (lpofn->hdr.code == CDN_SELCHANGE) {
+          HWND parentHWND = GetParent(hwnd);
+
+          // Get the required size for the selected files buffer
+          UINT newBufLength = 0; 
+          int requiredBufLength = CommDlg_OpenSave_GetSpecW(parentHWND, 
+                                                            nullptr, 0);
+          if(requiredBufLength >= 0)
+            newBufLength += requiredBufLength;
+          else
+            newBufLength += MAX_PATH;
+
+          // If the user selects multiple files, the buffer contains the 
+          // current directory followed by the file names of the selected 
+          // files. So make room for the directory path.  If the user
+          // selects a single file, it is no harm to add extra space.
+          requiredBufLength = CommDlg_OpenSave_GetFolderPathW(parentHWND, 
+                                                              nullptr, 0);
+          if(requiredBufLength >= 0)
+            newBufLength += requiredBufLength;
+          else
+            newBufLength += MAX_PATH;
+
+          // Check if lpstrFile and nMaxFile are large enough
+          if (newBufLength > lpofn->lpOFN->nMaxFile) {
+            if (lpofn->lpOFN->lpstrFile)
+              delete[] lpofn->lpOFN->lpstrFile;
+
+            // We allocate FILE_BUFFER_SIZE more bytes than is needed so that
+            // if the user selects a file and holds down shift and down to 
+            // select  additional items, we will not continuously reallocate
+            newBufLength += FILE_BUFFER_SIZE;
+
+            wchar_t* filesBuffer = new wchar_t[newBufLength];
+            ZeroMemory(filesBuffer, newBufLength * sizeof(wchar_t));
+
+            lpofn->lpOFN->lpstrFile = filesBuffer;
+            lpofn->lpOFN->nMaxFile  = newBufLength;
+          }
+        }
+      }
+      break;
+    case WM_TIMER:
+      {
+        // Check to see if our parent has been torn down, if so, we close too.
+        if (wParam == kDialogTimerID) {
+          nsFilePicker* picker =
+            reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
+          if (picker && picker->ClosePickerIfNeeded(true)) {
+            KillTimer(hwnd, kDialogTimerID);
+          }
+        }
+      }
+      break;
+  }
+
+  return FilePickerHook(hwnd, msg, wParam, lParam);
+}
 
 /*
  * Vista+ callbacks
@@ -290,18 +476,25 @@ nsFilePicker::OnOverwrite(IFileDialog *pfd,
  */
 
 bool
-nsFilePicker::ClosePickerIfNeeded()
+nsFilePicker::ClosePickerIfNeeded(bool aIsXPDialog)
 {
   if (!mParentWidget || !mDlgWnd)
     return false;
 
   nsWindow *win = static_cast<nsWindow *>(mParentWidget.get());
-  if (IsWindow(mDlgWnd) && IsWindowVisible(mDlgWnd) && win->DestroyCalled()) {
+  // Note, the xp callbacks hand us an inner window, so we have to step up
+  // one to get the actual dialog.
+  HWND dlgWnd;
+  if (aIsXPDialog)
+    dlgWnd = GetParent(mDlgWnd);
+  else
+    dlgWnd = mDlgWnd;
+  if (IsWindow(dlgWnd) && IsWindowVisible(dlgWnd) && win->DestroyCalled()) {
     wchar_t className[64];
     // Make sure we have the right window
-    if (GetClassNameW(mDlgWnd, className, mozilla::ArrayLength(className)) &&
+    if (GetClassNameW(dlgWnd, className, mozilla::ArrayLength(className)) &&
         !wcscmp(className, L"#32770") &&
-        DestroyWindow(mDlgWnd)) {
+        DestroyWindow(dlgWnd)) {
       mDlgWnd = nullptr;
       return true;
     }
@@ -313,7 +506,7 @@ void
 nsFilePicker::PickerCallbackTimerFunc(nsITimer *aTimer, void *aCtx)
 {
   nsFilePicker* picker = (nsFilePicker*)aCtx;
-  if (picker->ClosePickerIfNeeded()) {
+  if (picker->ClosePickerIfNeeded(false)) {
     aTimer->Cancel();
   }
 }
@@ -330,15 +523,62 @@ nsFilePicker::SetDialogHandle(HWND aWnd)
  * Folder picker invocation
  */
 
+// Open the older XP style folder picker dialog. We end up in this call
+// on XP systems or when platform is built without the longhorn SDK.
+bool
+nsFilePicker::ShowXPFolderPicker(const nsString& aInitialDir)
+{
+  bool result = false;
+
+  auto dirBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
+  wcsncpy(dirBuffer.get(), aInitialDir.get(), FILE_BUFFER_SIZE);
+  dirBuffer[FILE_BUFFER_SIZE-1] = '\0';
+
+  AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ?
+    mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
+
+  BROWSEINFOW browserInfo = {0};
+  browserInfo.pidlRoot       = nullptr;
+  browserInfo.pszDisplayName = dirBuffer.get();
+  browserInfo.lpszTitle      = mTitle.get();
+  browserInfo.ulFlags        = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
+  browserInfo.hwndOwner      = adtw.get(); 
+  browserInfo.iImage         = 0;
+  browserInfo.lParam         = reinterpret_cast<LPARAM>(this);
+
+  if (!aInitialDir.IsEmpty()) {
+    // the dialog is modal so that |initialDir.get()| will be valid in 
+    // BrowserCallbackProc. Thus, we don't need to clone it.
+    browserInfo.lParam = (LPARAM) aInitialDir.get();
+    browserInfo.lpfn   = &BrowseCallbackProc;
+  } else {
+    browserInfo.lParam = 0;
+    browserInfo.lpfn   = nullptr;
+  }
+
+  LPITEMIDLIST list = ::SHBrowseForFolderW(&browserInfo);
+  if (list) {
+    result = ::SHGetPathFromIDListW(list, dirBuffer.get());
+    if (result)
+      mUnicodeFile.Assign(static_cast<const wchar_t*>(dirBuffer.get()));
+    // free PIDL
+    CoTaskMemFree(list);
+  }
+
+  return result;
+}
+
 /*
- * Show a folder picker.
- *
+ * Show a folder picker post Windows XP
+ * 
  * @param aInitialDir   The initial directory, the last used directory will be
  *                      used if left blank.
+ * @param aWasInitError Out parameter will hold true if there was an error
+ *                      before the folder picker is shown.
  * @return true if a file was selected successfully.
 */
 bool
-nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
+nsFilePicker::ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError)
 {
   if (!IsWin8OrLater()) {
     // Some Windows 7 users are experiencing a race condition when some dlls
@@ -353,8 +593,10 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
   if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
                               IID_IFileOpenDialog,
                               getter_AddRefs(dialog)))) {
+    aWasInitError = true;
     return false;
   }
+  aWasInitError = false;
 
   // hook up event callbacks
   dialog->Advise(this, &mFDECookie);
@@ -416,15 +658,233 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
  * File open and save picker invocation
  */
 
+/* static */ bool
+nsFilePicker::GetFileNameWrapper(OPENFILENAMEW* ofn, PickerType aType)
+{
+  MOZ_SEH_TRY {
+    if (aType == PICKER_TYPE_OPEN)
+      return ::GetOpenFileNameW(ofn);
+    else if (aType == PICKER_TYPE_SAVE)
+      return ::GetSaveFileNameW(ofn);
+  } MOZ_SEH_EXCEPT(true) {
+    NS_ERROR("nsFilePicker GetFileName win32 call generated an exception! This is bad!");
+  }
+  return false;
+}
+
+bool
+nsFilePicker::FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType)
+{
+  if (!ofn)
+    return false;
+  AutoWidgetPickerState awps(mParentWidget);
+  return GetFileNameWrapper(ofn, aType);
+}
+
+bool
+nsFilePicker::ShowXPFilePicker(const nsString& aInitialDir)
+{
+  OPENFILENAMEW ofn = {0};
+  ofn.lStructSize = sizeof(ofn);
+  nsString filterBuffer = mFilterList;
+                                
+  auto fileBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
+  wcsncpy(fileBuffer.get(),  mDefaultFilePath.get(), FILE_BUFFER_SIZE);
+  fileBuffer[FILE_BUFFER_SIZE-1] = '\0'; // null terminate in case copy truncated
+
+  if (!aInitialDir.IsEmpty()) {
+    ofn.lpstrInitialDir = aInitialDir.get();
+  }
+
+  AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
+    mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
+
+  ofn.lpstrTitle   = (LPCWSTR)mTitle.get();
+  ofn.lpstrFilter  = (LPCWSTR)filterBuffer.get();
+  ofn.nFilterIndex = mSelectedType;
+  ofn.lpstrFile    = fileBuffer.get();
+  ofn.nMaxFile     = FILE_BUFFER_SIZE;
+  ofn.hwndOwner    = adtw.get();
+  ofn.lCustData    = reinterpret_cast<LPARAM>(this);
+  ofn.Flags = OFN_SHAREAWARE | OFN_LONGNAMES | OFN_OVERWRITEPROMPT |
+              OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_ENABLESIZING | 
+              OFN_EXPLORER;
+
+  // Windows Vista and up won't allow you to use the new looking dialogs with
+  // a hook procedure.  The hook procedure fixes a problem on XP dialogs for
+  // file picker visibility.  Vista and up automatically ensures the file 
+  // picker is always visible.
+  if (!IsVistaOrLater()) {
+    ofn.lpfnHook = FilePickerHook;
+    ofn.Flags |= OFN_ENABLEHOOK;
+  }
+
+  // Handle add to recent docs settings
+  if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
+    ofn.Flags |= OFN_DONTADDTORECENT;
+  }
+
+  NS_NAMED_LITERAL_STRING(htmExt, "html");
+
+  if (!mDefaultExtension.IsEmpty()) {
+    ofn.lpstrDefExt = mDefaultExtension.get();
+  } else if (IsDefaultPathHtml()) {
+    // Get file extension from suggested filename to detect if we are
+    // saving an html file.
+    // This is supposed to append ".htm" if user doesn't supply an
+    // extension but the behavior is sort of weird:
+    // - Often appends ".html" even if you have an extension
+    // - It obeys your extension if you put quotes around name
+    ofn.lpstrDefExt = htmExt.get();
+  }
+
+  // When possible, instead of using OFN_NOCHANGEDIR to ensure the current
+  // working directory will not change from this call, we will retrieve the
+  // current working directory before the call and restore it after the 
+  // call.  This flag causes problems on Windows XP for paths that are
+  // selected like  C:test.txt where the user is currently at C:\somepath
+  // In which case expected result should be C:\somepath\test.txt
+  AutoRestoreWorkingPath restoreWorkingPath;
+  // If we can't get the current working directory, the best case is to
+  // use the OFN_NOCHANGEDIR flag
+  if (!restoreWorkingPath.HasWorkingPath()) {
+    ofn.Flags |= OFN_NOCHANGEDIR;
+  }
+
+  bool result = false;
+
+  switch(mMode) {
+    case modeOpen:
+      // FILE MUST EXIST!
+      ofn.Flags |= OFN_FILEMUSTEXIST;
+      result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
+      break;
+
+    case modeOpenMultiple:
+      ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
+
+      // The hook set here ensures that the buffer returned will always be
+      // large enough to hold all selected files.  The hook may modify the
+      // value of ofn.lpstrFile and deallocate the old buffer that it pointed
+      // to (fileBuffer). The hook assumes that the passed in value is heap 
+      // allocated and that the returned value should be freed by the caller.
+      // If the hook changes the buffer, it will deallocate the old buffer.
+      // This fix would be nice to have in Vista and up, but it would force
+      // the file picker to use the old style dialogs because hooks are not
+      // allowed in the new file picker UI.  We need to eventually move to
+      // the new Common File Dialogs for Vista and up.
+      if (!IsVistaOrLater()) {
+        ofn.lpfnHook = MultiFilePickerHook;
+        fileBuffer.release();
+        result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
+        fileBuffer.reset(ofn.lpstrFile);
+      } else {
+        result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
+      }
+      break;
+
+    case modeSave:
+      {
+        ofn.Flags |= OFN_NOREADONLYRETURN;
+
+        // Don't follow shortcuts when saving a shortcut, this can be used
+        // to trick users (bug 271732)
+        if (IsDefaultPathLink())
+          ofn.Flags |= OFN_NODEREFERENCELINKS;
+
+        result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
+        if (!result) {
+          // Error, find out what kind.
+          if (GetLastError() == ERROR_INVALID_PARAMETER ||
+              CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
+            // Probably the default file name is too long or contains illegal
+            // characters. Try again, without a starting file name.
+            ofn.lpstrFile[0] = L'\0';
+            result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
+          }
+        }
+      }
+      break;
+
+    default:
+      NS_NOTREACHED("unsupported file picker mode");
+      return false;
+  }
+
+  if (!result)
+    return false;
+
+  // Remember what filter type the user selected
+  mSelectedType = (int16_t)ofn.nFilterIndex;
+
+  // Single file selection, we're done
+  if (mMode != modeOpenMultiple) {
+    GetQualifiedPath(fileBuffer.get(), mUnicodeFile);
+    return true;
+  }
+
+  // Set user-selected location of file or directory.  From msdn's "Open and
+  // Save As Dialog Boxes" section:
+  // If you specify OFN_EXPLORER, the directory and file name strings are '\0'
+  // separated, with an extra '\0' character after the last file name. This
+  // format enables the Explorer-style dialog boxes to return long file names
+  // that include spaces. 
+  wchar_t *current = fileBuffer.get();
+  
+  nsAutoString dirName(current);
+  // Sometimes dirName contains a trailing slash and sometimes it doesn't:
+  if (current[dirName.Length() - 1] != '\\')
+    dirName.Append((char16_t)'\\');
+  
+  while (current && *current && *(current + wcslen(current) + 1)) {
+    current = current + wcslen(current) + 1;
+    
+    nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
+    NS_ENSURE_TRUE(file, false);
+
+    // Only prepend the directory if the path specified is a relative path
+    nsAutoString path;
+    if (PathIsRelativeW(current)) {
+      path = dirName + nsDependentString(current);
+    } else {
+      path = current;
+    }
+
+    nsAutoString canonicalizedPath;
+    GetQualifiedPath(path.get(), canonicalizedPath);
+    if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
+        !mFiles.AppendObject(file))
+      return false;
+  }
+  
+  // Handle the case where the user selected just one file. From msdn: If you
+  // specify OFN_ALLOWMULTISELECT and the user selects only one file the
+  // lpstrFile string does not have a separator between the path and file name.
+  if (current && *current && (current == fileBuffer.get())) {
+    nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
+    NS_ENSURE_TRUE(file, false);
+    
+    nsAutoString canonicalizedPath;
+    GetQualifiedPath(current, canonicalizedPath);
+    if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
+        !mFiles.AppendObject(file))
+      return false;
+  }
+
+  return true;
+}
+
 /*
- * Show a file picker.
- *
+ * Show a file picker post Windows XP
+ * 
  * @param aInitialDir   The initial directory, the last used directory will be
  *                      used if left blank.
+ * @param aWasInitError Out parameter will hold true if there was an error
+ *                      before the file picker is shown.
  * @return true if a file was selected successfully.
 */
 bool
-nsFilePicker::ShowFilePicker(const nsString& aInitialDir)
+nsFilePicker::ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
 
@@ -442,15 +902,18 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir)
     if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
                                 IID_IFileOpenDialog,
                                 getter_AddRefs(dialog)))) {
+      aWasInitError = true;
       return false;
     }
   } else {
     if (FAILED(CoCreateInstance(CLSID_FileSaveDialog, nullptr, CLSCTX_INPROC,
                                 IID_IFileSaveDialog,
                                 getter_AddRefs(dialog)))) {
+      aWasInitError = true;
       return false;
     }
   }
+  aWasInitError = false;
 
   // hook up event callbacks
   dialog->Advise(this, &mFDECookie);
@@ -617,11 +1080,22 @@ nsFilePicker::ShowW(int16_t *aReturnVal)
   // with our context set temporarily to system-dpi-aware
   WinUtils::AutoSystemDpiAware dpiAwareness;
 
-  bool result = false;
+  // Launch the XP file/folder picker on XP and as a fallback on Vista+. 
+  // The CoCreateInstance call to CLSID_FileOpenDialog fails with "(0x80040111)
+  // ClassFactory cannot supply requested class" when the checkbox for
+  // Disable Visual Themes is on in the compatability tab within the shortcut
+  // properties.
+  bool result = false, wasInitError = true;
   if (mMode == modeGetFolder) {
-    result = ShowFolderPicker(initialDir);
+    if (IsVistaOrLater())
+      result = ShowFolderPicker(initialDir, wasInitError);
+    if (!result && wasInitError)
+      result = ShowXPFolderPicker(initialDir);
   } else {
-    result = ShowFilePicker(initialDir);
+    if (IsVistaOrLater())
+      result = ShowFilePicker(initialDir, wasInitError);
+    if (!result && wasInitError)
+      result = ShowXPFilePicker(initialDir);
   }
 
   // exit, and return returnCancel in aReturnVal
@@ -773,10 +1247,48 @@ nsFilePicker::InitNative(nsIWidget *aParent,
   mTitle.Assign(aTitle);
 }
 
+void 
+nsFilePicker::GetQualifiedPath(const wchar_t *aInPath, nsString &aOutPath)
+{
+  // Prefer a qualified path over a non qualified path.
+  // Things like c:file.txt would be accepted in Win XP but would later
+  // fail to open from the download manager.
+  wchar_t qualifiedFileBuffer[MAX_PATH];
+  if (PathSearchAndQualifyW(aInPath, qualifiedFileBuffer, MAX_PATH)) {
+    aOutPath.Assign(qualifiedFileBuffer);
+  } else {
+    aOutPath.Assign(aInPath);
+  }
+}
+
+void
+nsFilePicker::AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter)
+{
+  mFilterList.Append(aTitle);
+  mFilterList.Append(char16_t('\0'));
+
+  if (aFilter.EqualsLiteral("..apps"))
+    mFilterList.AppendLiteral("*.exe;*.com");
+  else
+  {
+    nsAutoString filter(aFilter);
+    filter.StripWhitespace();
+    if (filter.EqualsLiteral("*"))
+      filter.AppendLiteral(".*");
+    mFilterList.Append(filter);
+  }
+
+  mFilterList.Append(char16_t('\0'));
+}
+
 NS_IMETHODIMP
 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
 {
-  mComFilterList.Append(aTitle, aFilter);
+  if (IsVistaOrLater()) {
+    mComFilterList.Append(aTitle, aFilter);
+  } else {
+    AppendXPFilter(aTitle, aFilter);
+  }
   return NS_OK;
 }
 
diff --git a/widget/windows/nsFilePicker.h b/widget/windows/nsFilePicker.h
index 3d692b3d4..90d8c15bc 100644
--- a/widget/windows/nsFilePicker.h
+++ b/widget/windows/nsFilePicker.h
@@ -87,19 +87,32 @@ public:
   HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse);
 
 protected:
+  enum PickerType {
+    PICKER_TYPE_OPEN,
+    PICKER_TYPE_SAVE,
+  };
+
   /* method from nsBaseFilePicker */
   virtual void InitNative(nsIWidget *aParent,
                           const nsAString& aTitle);
+  static void GetQualifiedPath(const wchar_t *aInPath, nsString &aOutPath);
   void GetFilterListArray(nsString& aFilterList);
-  bool ShowFolderPicker(const nsString& aInitialDir);
-  bool ShowFilePicker(const nsString& aInitialDir);
+  static bool GetFileNameWrapper(OPENFILENAMEW* ofn, PickerType aType);
+  bool FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType);
+  bool ShowXPFolderPicker(const nsString& aInitialDir);
+  bool ShowXPFilePicker(const nsString& aInitialDir);
+  bool ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError);
+  bool ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError);
+  void AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter);
   void RememberLastUsedDirectory();
   bool IsPrivacyModeEnabled();
   bool IsDefaultPathLink();
   bool IsDefaultPathHtml();
   void SetDialogHandle(HWND aWnd);
-  bool ClosePickerIfNeeded();
+  bool ClosePickerIfNeeded(bool aIsXPDialog);
   static void PickerCallbackTimerFunc(nsITimer *aTimer, void *aPicker);
+  static UINT_PTR CALLBACK MultiFilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+  static UINT_PTR CALLBACK FilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
 
   nsCOMPtr<nsILoadContext> mLoadContext;
   nsCOMPtr<nsIWidget>    mParentWidget;
