diff --git a/accessible/windows/ia2/ia2Accessible.cpp b/accessible/windows/ia2/ia2Accessible.cpp
index 97cd0d788..c72719b51 100644
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -63,6 +63,8 @@ ia2Accessible::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2Accessible::get_nRelations(long* aNRelations)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNRelations)
     return E_INVALIDARG;
   *aNRelations = 0;
@@ -82,12 +84,16 @@ ia2Accessible::get_nRelations(long* aNRelations)
       (*aNRelations)++;
   }
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_relation(long aRelationIndex,
                             IAccessibleRelation** aRelation)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRelation || aRelationIndex < 0)
     return E_INVALIDARG;
   *aRelation = nullptr;
@@ -118,6 +124,8 @@ ia2Accessible::get_relation(long aRelationIndex,
   }
 
   return E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -125,6 +133,8 @@ ia2Accessible::get_relations(long aMaxRelations,
                              IAccessibleRelation** aRelation,
                              long *aNRelations)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRelation || !aNRelations || aMaxRelations <= 0)
     return E_INVALIDARG;
   *aNRelations = 0;
@@ -150,11 +160,15 @@ ia2Accessible::get_relations(long aMaxRelations,
     }
   }
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::role(long* aRole)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRole)
     return E_INVALIDARG;
   *aRole = 0;
@@ -190,11 +204,15 @@ ia2Accessible::role(long* aRole)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::scrollTo(enum IA2ScrollType aScrollType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
@@ -204,12 +222,16 @@ ia2Accessible::scrollTo(enum IA2ScrollType aScrollType)
                         aScrollType);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::scrollToPoint(enum IA2CoordinateType aCoordType,
                               long aX, long aY)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
@@ -222,6 +244,8 @@ ia2Accessible::scrollToPoint(enum IA2CoordinateType aCoordType,
   acc->ScrollToPoint(geckoCoordType, aX, aY);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -229,6 +253,8 @@ ia2Accessible::get_groupPosition(long* aGroupLevel,
                                  long* aSimilarItemsInGroup,
                                  long* aPositionInGroup)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aGroupLevel || !aSimilarItemsInGroup || !aPositionInGroup)
     return E_INVALIDARG;
 
@@ -253,11 +279,15 @@ ia2Accessible::get_groupPosition(long* aGroupLevel,
   *aPositionInGroup = groupPos.posInSet;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_states(AccessibleStates* aStates)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStates)
     return E_INVALIDARG;
   *aStates = 0;
@@ -317,36 +347,50 @@ ia2Accessible::get_states(AccessibleStates* aStates)
     *aStates |= IA2_STATE_PINNED;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_extendedRole(BSTR* aExtendedRole)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aExtendedRole)
     return E_INVALIDARG;
 
   *aExtendedRole = nullptr;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_localizedExtendedRole(BSTR* aLocalizedExtendedRole)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocalizedExtendedRole)
     return E_INVALIDARG;
 
   *aLocalizedExtendedRole = nullptr;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_nExtendedStates(long* aNExtendedStates)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNExtendedStates)
     return E_INVALIDARG;
 
   *aNExtendedStates = 0;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -354,12 +398,16 @@ ia2Accessible::get_extendedStates(long aMaxExtendedStates,
                                   BSTR** aExtendedStates,
                                   long* aNExtendedStates)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aExtendedStates || !aNExtendedStates)
     return E_INVALIDARG;
 
   *aExtendedStates = nullptr;
   *aNExtendedStates = 0;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -367,28 +415,38 @@ ia2Accessible::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
                                            BSTR** aLocalizedExtendedStates,
                                            long* aNLocalizedExtendedStates)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocalizedExtendedStates || !aNLocalizedExtendedStates)
     return E_INVALIDARG;
 
   *aLocalizedExtendedStates = nullptr;
   *aNLocalizedExtendedStates = 0;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_uniqueID(long* aUniqueID)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aUniqueID)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   *aUniqueID = AccessibleWrap::GetChildIDFor(acc);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_windowHandle(HWND* aWindowHandle)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aWindowHandle)
     return E_INVALIDARG;
   *aWindowHandle = 0;
@@ -399,11 +457,15 @@ ia2Accessible::get_windowHandle(HWND* aWindowHandle)
 
   *aWindowHandle = AccessibleWrap::GetHWNDFor(acc);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_indexInParent(long* aIndexInParent)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIndexInParent)
     return E_INVALIDARG;
   *aIndexInParent = -1;
@@ -419,11 +481,15 @@ ia2Accessible::get_indexInParent(long* aIndexInParent)
     return S_FALSE;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_locale(IA2Locale* aLocale)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocale)
     return E_INVALIDARG;
 
@@ -466,11 +532,15 @@ ia2Accessible::get_locale(IA2Locale* aLocale)
   // country abbreviations or if there are more than one subcode.
   aLocale->variant = ::SysAllocString(lang.get());
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_attributes(BSTR* aAttributes)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAttributes)
     return E_INVALIDARG;
   *aAttributes = nullptr;
@@ -488,6 +558,8 @@ ia2Accessible::get_attributes(BSTR* aAttributes)
 
   MOZ_ASSERT(!acc->IsProxy());
   return E_UNEXPECTED;
+
+  A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -496,16 +568,22 @@ ia2Accessible::get_attributes(BSTR* aAttributes)
 STDMETHODIMP
 ia2Accessible::get_attribute(BSTR name, VARIANT* aAttribute)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAttribute)
     return E_INVALIDARG;
 
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
                                        long* aCaretOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccessible || !aCaretOffset)
     return E_INVALIDARG;
 
@@ -533,6 +611,8 @@ ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
   (*aAccessible)->AddRef();
   *aCaretOffset = caretOffset;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -541,6 +621,8 @@ ia2Accessible::get_relationTargetsOfType(BSTR aType,
                                          IUnknown*** aTargets,
                                          long* aNTargets)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aTargets || !aNTargets || aMaxTargets < 0)
     return E_INVALIDARG;
   *aNTargets = 0;
@@ -581,12 +663,16 @@ ia2Accessible::get_relationTargetsOfType(BSTR aType,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_selectionRanges(IA2Range** aRanges,
                                    long *aNRanges)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRanges || !aNRanges)
     return E_INVALIDARG;
 
@@ -628,6 +714,8 @@ ia2Accessible::get_selectionRanges(IA2Range** aRanges,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 
diff --git a/accessible/windows/ia2/ia2AccessibleAction.cpp b/accessible/windows/ia2/ia2AccessibleAction.cpp
index ffd19f049..0710b753f 100644
--- a/accessible/windows/ia2/ia2AccessibleAction.cpp
+++ b/accessible/windows/ia2/ia2AccessibleAction.cpp
@@ -39,6 +39,8 @@ ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleAction::nActions(long* aActionCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aActionCount)
     return E_INVALIDARG;
 
@@ -50,22 +52,30 @@ ia2AccessibleAction::nActions(long* aActionCount)
 
   *aActionCount = acc->ActionCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::doAction(long aActionIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   uint8_t index = static_cast<uint8_t>(aActionIndex);
   return acc->DoAction(index) ? S_OK : E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aDescription)
     return E_INVALIDARG;
   *aDescription = nullptr;
@@ -83,6 +93,8 @@ ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
   *aDescription = ::SysAllocStringLen(description.get(),
                                       description.Length());
   return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -90,6 +102,8 @@ ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
                                   BSTR **aKeyBinding,
                                   long *aNumBinding)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aKeyBinding)
     return E_INVALIDARG;
   *aKeyBinding = nullptr;
@@ -129,11 +143,15 @@ ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
 
   *aNumBinding = 1;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aName)
     return E_INVALIDARG;
 
@@ -151,14 +169,20 @@ ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
 
   *aName = ::SysAllocStringLen(name.get(), name.Length());
   return *aName ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocalizedName)
     return E_INVALIDARG;
 
   *aLocalizedName = nullptr;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/ia2/ia2AccessibleComponent.cpp b/accessible/windows/ia2/ia2AccessibleComponent.cpp
index 2c9cd0ab4..f32c09d1e 100644
--- a/accessible/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/windows/ia2/ia2AccessibleComponent.cpp
@@ -41,6 +41,8 @@ ia2AccessibleComponent::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleComponent::get_locationInParent(long* aX, long* aY)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aX || !aY)
     return E_INVALIDARG;
 
@@ -73,11 +75,15 @@ ia2AccessibleComponent::get_locationInParent(long* aX, long* aY)
   *aX = rect.x - parentRect.x;
   *aY = rect.y - parentRect.y;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleComponent::get_foreground(IA2Color* aForeground)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aForeground)
     return E_INVALIDARG;
 
@@ -92,11 +98,15 @@ ia2AccessibleComponent::get_foreground(IA2Color* aForeground)
     *aForeground = frame->StyleColor()->mColor;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleComponent::get_background(IA2Color* aBackground)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aBackground)
     return E_INVALIDARG;
 
@@ -111,5 +121,7 @@ ia2AccessibleComponent::get_background(IA2Color* aBackground)
     *aBackground = frame->StyleBackground()->mBackgroundColor;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/ia2/ia2AccessibleEditableText.cpp b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
index 0b433bf6d..361d6a130 100644
--- a/accessible/windows/ia2/ia2AccessibleEditableText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
@@ -22,6 +22,8 @@ using namespace mozilla::a11y;
 STDMETHODIMP
 ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -33,11 +35,15 @@ ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
 
   textAcc->CopyText(aStartOffset, aEndOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -49,11 +55,15 @@ ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
 
   textAcc->DeleteText(aStartOffset, aEndOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   uint32_t length = ::SysStringLen(*aText);
   nsAutoString text(*aText, length);
   MOZ_ASSERT(!HyperTextProxyFor(this));
@@ -67,11 +77,15 @@ ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
 
   textAcc->InsertText(text, aOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -83,11 +97,15 @@ ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
 
   textAcc->CutText(aStartOffset, aEndOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::pasteText(long aOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -99,12 +117,16 @@ ia2AccessibleEditableText::pasteText(long aOffset)
 
   textAcc->PasteText(aOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
                                        BSTR *aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
@@ -119,6 +141,8 @@ ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
   textAcc->InsertText(text, aStartOffset);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
diff --git a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
index d36c0ef25..c6d564103 100644
--- a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -45,6 +45,8 @@ ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAnchor)
     return E_INVALIDARG;
 
@@ -75,11 +77,15 @@ ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
   aAnchor->punkVal = static_cast<IUnknown*>(instancePtr);
   aAnchor->vt = VT_UNKNOWN;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAnchorTarget) {
     return E_INVALIDARG;
   }
@@ -118,11 +124,15 @@ ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
   aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
                                                stringURI.Length());
   return aAnchorTarget->bstrVal ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_startIndex(long* aIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIndex)
     return E_INVALIDARG;
 
@@ -139,11 +149,15 @@ ia2AccessibleHyperlink::get_startIndex(long* aIndex)
 
   *aIndex = thisObj->StartOffset();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_endIndex(long* aIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIndex)
     return E_INVALIDARG;
 
@@ -160,11 +174,15 @@ ia2AccessibleHyperlink::get_endIndex(long* aIndex)
 
   *aIndex = thisObj->EndOffset();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_valid(boolean* aValid)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aValid)
     return E_INVALIDARG;
 
@@ -181,5 +199,7 @@ ia2AccessibleHyperlink::get_valid(boolean* aValid)
 
   *aValid = thisObj->IsLinkValid();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/ia2/ia2AccessibleHypertext.cpp b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
index 555bde686..f4b3bdaf2 100644
--- a/accessible/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
@@ -19,6 +19,8 @@ using namespace mozilla::a11y;
 STDMETHODIMP
 ia2AccessibleHypertext::get_nHyperlinks(long* aHyperlinkCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aHyperlinkCount)
     return E_INVALIDARG;
 
@@ -32,12 +34,16 @@ ia2AccessibleHypertext::get_nHyperlinks(long* aHyperlinkCount)
 
   *aHyperlinkCount = hyperText->LinkCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
                                       IAccessibleHyperlink** aHyperlink)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aHyperlink)
     return E_INVALIDARG;
 
@@ -59,11 +65,15 @@ ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
     static_cast<IAccessibleHyperlink*>(hyperLink);
   (*aHyperlink)->AddRef();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aHyperlinkIndex)
     return E_INVALIDARG;
 
@@ -77,5 +87,7 @@ ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkInde
 
   *aHyperlinkIndex = hyperAcc->LinkIndexAtOffset(aCharIndex);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/ia2/ia2AccessibleImage.cpp b/accessible/windows/ia2/ia2AccessibleImage.cpp
index 7dc7f765c..989fde925 100644
--- a/accessible/windows/ia2/ia2AccessibleImage.cpp
+++ b/accessible/windows/ia2/ia2AccessibleImage.cpp
@@ -43,6 +43,8 @@ ia2AccessibleImage::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleImage::get_description(BSTR* aDescription)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aDescription)
     return E_INVALIDARG;
 
@@ -59,6 +61,8 @@ ia2AccessibleImage::get_description(BSTR* aDescription)
 
   *aDescription = ::SysAllocStringLen(description.get(), description.Length());
   return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -66,6 +70,8 @@ ia2AccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
                                       long* aX,
                                       long* aY)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aX || !aY)
     return E_INVALIDARG;
 
@@ -84,11 +90,15 @@ ia2AccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
   *aX = pos.x;
   *aY = pos.y;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleImage::get_imageSize(long* aHeight, long* aWidth)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aHeight || !aWidth)
     return E_INVALIDARG;
 
@@ -103,5 +113,7 @@ ia2AccessibleImage::get_imageSize(long* aHeight, long* aWidth)
   *aHeight = size.width;
   *aWidth = size.height;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/ia2/ia2AccessibleRelation.cpp b/accessible/windows/ia2/ia2AccessibleRelation.cpp
index 67435ee52..cc6fd83c8 100644
--- a/accessible/windows/ia2/ia2AccessibleRelation.cpp
+++ b/accessible/windows/ia2/ia2AccessibleRelation.cpp
@@ -34,6 +34,8 @@ IMPL_IUNKNOWN_QUERY_TAIL
 STDMETHODIMP
 ia2AccessibleRelation::get_relationType(BSTR* aRelationType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRelationType)
     return E_INVALIDARG;
 
@@ -49,31 +51,43 @@ ia2AccessibleRelation::get_relationType(BSTR* aRelationType)
   }
 
   return *aRelationType ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_localizedRelationType(BSTR *aLocalizedRelationType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocalizedRelationType)
     return E_INVALIDARG;
 
   *aLocalizedRelationType = nullptr;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_nTargets(long *aNTargets)
 {
+  A11Y_TRYBLOCK_BEGIN
+
  if (!aNTargets)
    return E_INVALIDARG;
 
  *aNTargets = mTargets.Length();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (aTargetIndex < 0 || (uint32_t)aTargetIndex >= mTargets.Length() || !aTarget)
     return E_INVALIDARG;
 
@@ -83,12 +97,16 @@ ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
   (*aTarget)->AddRef();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
                                    long *aNTargets)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNTargets || !aTargets)
     return E_INVALIDARG;
 
@@ -102,4 +120,6 @@ ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
 
   *aNTargets = maxTargets;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/ia2/ia2AccessibleTable.cpp b/accessible/windows/ia2/ia2AccessibleTable.cpp
index a99f72def..6ac6bbab4 100644
--- a/accessible/windows/ia2/ia2AccessibleTable.cpp
+++ b/accessible/windows/ia2/ia2AccessibleTable.cpp
@@ -60,6 +60,8 @@ ia2AccessibleTable::get_accessibleAt(long aRowIdx, long aColIdx,
 STDMETHODIMP
 ia2AccessibleTable::get_caption(IUnknown** aAccessible)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccessible)
     return E_INVALIDARG;
 
@@ -73,12 +75,16 @@ ia2AccessibleTable::get_caption(IUnknown** aAccessible)
 
   (*aAccessible = static_cast<IAccessible*>(caption))->AddRef();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
                                    long* aChildIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aChildIdx)
     return E_INVALIDARG;
 
@@ -93,11 +99,15 @@ ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
 
   *aChildIdx = mTable->CellIndexAt(aRowIdx, aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aDescription)
     return E_INVALIDARG;
 
@@ -115,12 +125,16 @@ ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
 
   *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
   return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
                                       long* aSpan)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aSpan)
     return E_INVALIDARG;
 
@@ -135,23 +149,31 @@ ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
 
   *aSpan = mTable->ColExtentAt(aRowIdx, aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
                                     long* aStartingRowIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccessibleTable || !aStartingRowIndex)
     return E_INVALIDARG;
 
   *aAccessibleTable = nullptr;
   *aStartingRowIndex = -1;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aColIdx)
     return E_INVALIDARG;
 
@@ -165,11 +187,15 @@ ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
 
   *aColIdx = mTable->ColIndexAt(aCellIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nColumns(long* aColCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aColCount)
     return E_INVALIDARG;
 
@@ -179,11 +205,15 @@ ia2AccessibleTable::get_nColumns(long* aColCount)
 
   *aColCount = mTable->ColCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nRows(long* aRowCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowCount)
     return E_INVALIDARG;
 
@@ -193,6 +223,8 @@ ia2AccessibleTable::get_nRows(long* aRowCount)
 
   *aRowCount = mTable->RowCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -204,6 +236,8 @@ ia2AccessibleTable::get_nSelectedChildren(long* aChildCount)
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aColCount)
     return E_INVALIDARG;
 
@@ -213,11 +247,15 @@ ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
 
   *aColCount = mTable->SelectedColCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowCount)
     return E_INVALIDARG;
 
@@ -228,11 +266,15 @@ ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
   *aRowCount = mTable->SelectedRowCount();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aDescription)
     return E_INVALIDARG;
 
@@ -250,11 +292,15 @@ ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
 
   *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
   return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aSpan)
     return E_INVALIDARG;
 
@@ -269,23 +315,31 @@ ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
 
   *aSpan = mTable->RowExtentAt(aRowIdx, aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
                                   long* aStartingColumnIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccessibleTable || !aStartingColumnIndex)
     return E_INVALIDARG;
 
   *aAccessibleTable = nullptr;
   *aStartingColumnIndex = -1;
   return E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowIdx)
     return E_INVALIDARG;
 
@@ -299,12 +353,16 @@ ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
 
   *aRowIdx = mTable->RowIndexAt(aCellIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
                                          long* aNChildren)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aChildren || !aNChildren)
     return E_INVALIDARG;
 
@@ -326,24 +384,36 @@ ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
     (*aChildren)[i] = cellIndices[i];
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedColumns(long aMaxColumns, long** aColumns,
                                         long* aNColumns)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   return get_selectedColumns(aColumns, aNColumns);
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedRows(long aMaxRows, long** aRows, long* aNRows)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   return get_selectedRows(aRows, aNRows);
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_summary(IUnknown** aAccessible)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccessible)
     return E_INVALIDARG;
 
@@ -354,11 +424,15 @@ ia2AccessibleTable::get_summary(IUnknown** aAccessible)
 
   *aAccessible = nullptr;
   return S_FALSE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIsSelected)
     return E_INVALIDARG;
 
@@ -371,11 +445,15 @@ ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
 
   *aIsSelected = mTable->IsColSelected(aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIsSelected)
     return E_INVALIDARG;
 
@@ -388,12 +466,16 @@ ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
 
   *aIsSelected = mTable->IsRowSelected(aRowIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
                                    boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIsSelected)
     return E_INVALIDARG;
 
@@ -408,11 +490,15 @@ ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
 
   *aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::selectRow(long aRowIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
@@ -421,11 +507,15 @@ ia2AccessibleTable::selectRow(long aRowIdx)
 
   mTable->SelectRow(aRowIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::selectColumn(long aColIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
@@ -434,11 +524,15 @@ ia2AccessibleTable::selectColumn(long aColIdx)
 
   mTable->SelectCol(aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::unselectRow(long aRowIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
@@ -447,11 +541,15 @@ ia2AccessibleTable::unselectRow(long aRowIdx)
 
   mTable->UnselectRow(aRowIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::unselectColumn(long aColIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
@@ -460,6 +558,8 @@ ia2AccessibleTable::unselectColumn(long aColIdx)
 
   mTable->UnselectCol(aColIdx);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -469,6 +569,8 @@ ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
                                                 long* aColExtents,
                                                 boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
     return E_INVALIDARG;
 
@@ -493,6 +595,8 @@ ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
   *aIsSelected = mTable->IsCellSelected(rowIdx, colIdx);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -507,6 +611,8 @@ ia2AccessibleTable::get_modelChange(IA2TableModelChange* aModelChange)
 STDMETHODIMP
 ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCell)
     return E_INVALIDARG;
 
@@ -522,11 +628,15 @@ ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
 
   (*aCell = static_cast<IAccessible*>(cell))->AddRef();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCellCount)
     return E_INVALIDARG;
 
@@ -536,11 +646,15 @@ ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
 
   *aCellCount = mTable->SelectedCellCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCells || !aNSelectedCells)
     return E_INVALIDARG;
 
@@ -568,11 +682,15 @@ ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
 
   *aNSelectedCells = cells.Length();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aColumns || !aNColumns)
     return E_INVALIDARG;
 
@@ -594,11 +712,15 @@ ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
     (*aColumns)[i] = colIndices[i];
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRows || !aNRows)
     return E_INVALIDARG;
 
@@ -620,4 +742,6 @@ ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
     (*aRows)[i] = rowIndices[i];
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/ia2/ia2AccessibleTableCell.cpp b/accessible/windows/ia2/ia2AccessibleTableCell.cpp
index 19cfc55da..e625a7049 100644
--- a/accessible/windows/ia2/ia2AccessibleTableCell.cpp
+++ b/accessible/windows/ia2/ia2AccessibleTableCell.cpp
@@ -46,6 +46,8 @@ ia2AccessibleTableCell::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleTableCell::get_table(IUnknown** aTable)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aTable)
     return E_INVALIDARG;
 
@@ -61,11 +63,15 @@ ia2AccessibleTableCell::get_table(IUnknown** aTable)
   *aTable = static_cast<IAccessible*>(wrap);
   (*aTable)->AddRef();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnExtent(long* aSpan)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aSpan)
     return E_INVALIDARG;
 
@@ -76,12 +82,16 @@ ia2AccessibleTableCell::get_columnExtent(long* aSpan)
   *aSpan = mTableCell->ColExtent();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
                                               long* aNColumnHeaderCells)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCellAccessibles || !aNColumnHeaderCells)
     return E_INVALIDARG;
 
@@ -108,11 +118,15 @@ ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnIndex(long* aColIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aColIdx)
     return E_INVALIDARG;
 
@@ -122,11 +136,15 @@ ia2AccessibleTableCell::get_columnIndex(long* aColIdx)
 
   *aColIdx = mTableCell->ColIdx();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowExtent(long* aSpan)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aSpan)
     return E_INVALIDARG;
 
@@ -136,12 +154,16 @@ ia2AccessibleTableCell::get_rowExtent(long* aSpan)
 
   *aSpan = mTableCell->RowExtent();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
                                            long* aNRowHeaderCells)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCellAccessibles || !aNRowHeaderCells)
     return E_INVALIDARG;
 
@@ -167,11 +189,15 @@ ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowIndex(long* aRowIdx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowIdx)
     return E_INVALIDARG;
 
@@ -181,6 +207,8 @@ ia2AccessibleTableCell::get_rowIndex(long* aRowIdx)
 
   *aRowIdx = mTableCell->RowIdx();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -189,6 +217,8 @@ ia2AccessibleTableCell::get_rowColumnExtents(long* aRowIdx, long* aColIdx,
                                              long* aColExtents,
                                              boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
     return E_INVALIDARG;
 
@@ -204,11 +234,15 @@ ia2AccessibleTableCell::get_rowColumnExtents(long* aRowIdx, long* aColIdx,
   *aIsSelected = mTableCell->Selected();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_isSelected(boolean* aIsSelected)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aIsSelected)
     return E_INVALIDARG;
 
@@ -218,4 +252,6 @@ ia2AccessibleTableCell::get_isSelected(boolean* aIsSelected)
 
   *aIsSelected = mTableCell->Selected();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/ia2/ia2AccessibleText.cpp b/accessible/windows/ia2/ia2AccessibleText.cpp
index 86b3abdf6..7ac766f30 100644
--- a/accessible/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleText.cpp
@@ -28,6 +28,8 @@ bool ia2AccessibleText::sLastTextChangeWasInsert = false;
 STDMETHODIMP
 ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -36,12 +38,16 @@ ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
 
   return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
     S_OK : E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
                                   long *aEndOffset, BSTR *aTextAttributes)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStartOffset || !aEndOffset || !aTextAttributes)
     return E_INVALIDARG;
 
@@ -68,11 +74,15 @@ ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
   *aEndOffset = endOffset;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_caretOffset(long *aOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aOffset)
     return E_INVALIDARG;
 
@@ -87,6 +97,8 @@ ia2AccessibleText::get_caretOffset(long *aOffset)
   *aOffset = textAcc->CaretOffset();
 
   return *aOffset != -1 ? S_OK : S_FALSE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -95,6 +107,8 @@ ia2AccessibleText::get_characterExtents(long aOffset,
                                         long* aX, long* aY,
                                         long* aWidth, long* aHeight)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aX || !aY || !aWidth || !aHeight)
     return E_INVALIDARG;
   *aX = *aY = *aWidth = *aHeight = 0;
@@ -115,11 +129,15 @@ ia2AccessibleText::get_characterExtents(long aOffset,
   *aWidth = rect.width;
   *aHeight = rect.height;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_nSelections(long* aNSelections)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNSelections)
     return E_INVALIDARG;
   *aNSelections = 0;
@@ -133,6 +151,8 @@ ia2AccessibleText::get_nSelections(long* aNSelections)
   *aNSelections = textAcc->SelectionCount();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -140,6 +160,8 @@ ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
                                      enum IA2CoordinateType aCoordType,
                                      long* aOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aOffset)
     return E_INVALIDARG;
   *aOffset = 0;
@@ -157,12 +179,16 @@ ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
   *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
 
   return *aOffset == -1 ? S_FALSE : S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
                                  long* aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStartOffset || !aEndOffset)
     return E_INVALIDARG;
   *aStartOffset = *aEndOffset = 0;
@@ -181,11 +207,15 @@ ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aText)
     return E_INVALIDARG;
 
@@ -209,6 +239,8 @@ ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText)
 
   *aText = ::SysAllocStringLen(text.get(), text.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -217,6 +249,8 @@ ia2AccessibleText::get_textBeforeOffset(long aOffset,
                                         long* aStartOffset, long* aEndOffset,
                                         BSTR* aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStartOffset || !aEndOffset || !aText)
     return E_INVALIDARG;
 
@@ -253,6 +287,8 @@ ia2AccessibleText::get_textBeforeOffset(long aOffset,
 
   *aText = ::SysAllocStringLen(text.get(), text.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -261,6 +297,8 @@ ia2AccessibleText::get_textAfterOffset(long aOffset,
                                        long* aStartOffset, long* aEndOffset,
                                        BSTR* aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStartOffset || !aEndOffset || !aText)
     return E_INVALIDARG;
 
@@ -297,6 +335,8 @@ ia2AccessibleText::get_textAfterOffset(long aOffset,
 
   *aText = ::SysAllocStringLen(text.get(), text.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -305,6 +345,8 @@ ia2AccessibleText::get_textAtOffset(long aOffset,
                                     long* aStartOffset, long* aEndOffset,
                                     BSTR* aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStartOffset || !aEndOffset || !aText)
     return E_INVALIDARG;
 
@@ -339,11 +381,15 @@ ia2AccessibleText::get_textAtOffset(long aOffset,
 
   *aText = ::SysAllocStringLen(text.get(), text.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::removeSelection(long aSelectionIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -352,11 +398,15 @@ ia2AccessibleText::removeSelection(long aSelectionIndex)
 
   return textAcc->RemoveFromSelection(aSelectionIndex) ?
     S_OK : E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::setCaretOffset(long aOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -368,12 +418,16 @@ ia2AccessibleText::setCaretOffset(long aOffset)
 
   textAcc->SetCaretOffset(aOffset);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
                                 long aEndOffset)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -382,11 +436,15 @@ ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
 
   return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ?
     S_OK : E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_nCharacters(long* aNCharacters)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNCharacters)
     return E_INVALIDARG;
   *aNCharacters = 0;
@@ -399,12 +457,16 @@ ia2AccessibleText::get_nCharacters(long* aNCharacters)
 
   *aNCharacters  = textAcc->CharacterCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
                                      enum IA2ScrollType aScrollType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -416,6 +478,8 @@ ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
 
   textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -423,6 +487,8 @@ ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
                                           enum IA2CoordinateType aCoordType,
                                           long aX, long aY)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
     nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
     nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
@@ -439,18 +505,28 @@ ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
   textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
                                   geckoCoordType, aX, aY);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   return GetModifiedText(true, aNewText);
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   return GetModifiedText(false, aOldText);
+
+  A11Y_TRYBLOCK_END
 }
 
 // ia2AccessibleText
diff --git a/accessible/windows/ia2/ia2AccessibleValue.cpp b/accessible/windows/ia2/ia2AccessibleValue.cpp
index 44d2c31fb..e33442295 100644
--- a/accessible/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/windows/ia2/ia2AccessibleValue.cpp
@@ -46,6 +46,8 @@ ia2AccessibleValue::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ia2AccessibleValue::get_currentValue(VARIANT* aCurrentValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCurrentValue)
     return E_INVALIDARG;
 
@@ -66,11 +68,15 @@ ia2AccessibleValue::get_currentValue(VARIANT* aCurrentValue)
   aCurrentValue->vt = VT_R8;
   aCurrentValue->dblVal = currentValue;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::setCurrentValue(VARIANT aValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (aValue.vt != VT_R8)
     return E_INVALIDARG;
 
@@ -81,11 +87,15 @@ ia2AccessibleValue::setCurrentValue(VARIANT aValue)
     return CO_E_OBJNOTCONNECTED;
 
   return valueAcc->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aMaximumValue)
     return E_INVALIDARG;
 
@@ -106,11 +116,15 @@ ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
   aMaximumValue->vt = VT_R8;
   aMaximumValue->dblVal = maximumValue;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_minimumValue(VARIANT* aMinimumValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aMinimumValue)
     return E_INVALIDARG;
 
@@ -131,5 +145,7 @@ ia2AccessibleValue::get_minimumValue(VARIANT* aMinimumValue)
   aMinimumValue->vt = VT_R8;
   aMinimumValue->dblVal = minimumValue;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/msaa/AccessibleWrap.cpp b/accessible/windows/msaa/AccessibleWrap.cpp
index 426270814..6112c370a 100644
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -110,6 +110,8 @@ AccessibleWrap::Shutdown()
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!ppv)
     return E_INVALIDARG;
 
@@ -163,6 +165,8 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 //-----------------------------------------------------
@@ -172,6 +176,8 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 AccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!ppdispParent)
     return E_INVALIDARG;
 
@@ -202,11 +208,15 @@ AccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
 
   *ppdispParent = NativeAccessible(xpParentAcc);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pcountChildren)
     return E_INVALIDARG;
 
@@ -220,6 +230,8 @@ AccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)
 
   *pcountChildren = ChildCount();
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -227,6 +239,8 @@ AccessibleWrap::get_accChild(
       /* [in] */ VARIANT varChild,
       /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!ppdispChild)
     return E_INVALIDARG;
 
@@ -251,6 +265,8 @@ AccessibleWrap::get_accChild(
 
   child.forget(ppdispChild);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 /**
@@ -315,6 +331,8 @@ AccessibleWrap::get_accName(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszName)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszName || varChild.vt != VT_I4)
     return E_INVALIDARG;
 
@@ -343,6 +361,8 @@ AccessibleWrap::get_accName(
   if (!*pszName)
     return E_OUTOFMEMORY;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 
@@ -351,6 +371,8 @@ AccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszValue)
     return E_INVALIDARG;
 
@@ -379,12 +401,16 @@ AccessibleWrap::get_accValue(
   if (!*pszValue)
     return E_OUTOFMEMORY;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accDescription(VARIANT varChild,
                                    BSTR __RPC_FAR *pszDescription)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszDescription)
     return E_INVALIDARG;
 
@@ -406,6 +432,8 @@ AccessibleWrap::get_accDescription(VARIANT varChild,
   *pszDescription = ::SysAllocStringLen(description.get(),
                                         description.Length());
   return *pszDescription ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -413,6 +441,8 @@ AccessibleWrap::get_accRole(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarRole)
     return E_INVALIDARG;
 
@@ -502,6 +532,8 @@ AccessibleWrap::get_accRole(
   }
 
   return E_FAIL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -509,6 +541,8 @@ AccessibleWrap::get_accState(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarState)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarState)
     return E_INVALIDARG;
 
@@ -540,6 +574,8 @@ AccessibleWrap::get_accState(
   nsAccUtils::To32States(state, &msaaState, nullptr);
   pvarState->lVal = msaaState;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 
@@ -548,11 +584,15 @@ AccessibleWrap::get_accHelp(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszHelp)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszHelp)
     return E_INVALIDARG;
 
   *pszHelp = nullptr;
   return S_FALSE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -561,12 +601,16 @@ AccessibleWrap::get_accHelpTopic(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ long __RPC_FAR *pidTopic)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszHelpFile || !pidTopic)
     return E_INVALIDARG;
 
   *pszHelpFile = nullptr;
   *pidTopic = 0;
   return S_FALSE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -574,6 +618,8 @@ AccessibleWrap::get_accKeyboardShortcut(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszKeyboardShortcut)
     return E_INVALIDARG;
   *pszKeyboardShortcut = nullptr;
@@ -599,12 +645,16 @@ AccessibleWrap::get_accKeyboardShortcut(
   *pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
                                              shortcut.Length());
   return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accFocus(
       /* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarChild)
     return E_INVALIDARG;
 
@@ -635,6 +685,8 @@ AccessibleWrap::get_accFocus(
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 /**
@@ -671,6 +723,8 @@ private:
 STDMETHODIMP
 AccessibleEnumerator::QueryInterface(REFIID iid, void ** ppvObject)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (iid == IID_IEnumVARIANT) {
     *ppvObject = static_cast<IEnumVARIANT*>(this);
     AddRef();
@@ -684,11 +738,15 @@ AccessibleEnumerator::QueryInterface(REFIID iid, void ** ppvObject)
 
   *ppvObject = nullptr;
   return E_NOINTERFACE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleEnumerator::Next(unsigned long celt, VARIANT FAR* rgvar, unsigned long FAR* pceltFetched)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   uint32_t length = mArray.Length();
   HRESULT hr = S_OK;
 
@@ -708,21 +766,29 @@ AccessibleEnumerator::Next(unsigned long celt, VARIANT FAR* rgvar, unsigned long
     *pceltFetched = celt;
 
   return hr;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleEnumerator::Clone(IEnumVARIANT FAR* FAR* ppenum)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   *ppenum = new AccessibleEnumerator(*this);
   if (!*ppenum)
     return E_OUTOFMEMORY;
   NS_ADDREF(*ppenum);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleEnumerator::Skip(unsigned long celt)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   uint32_t length = mArray.Length();
   // Check if we can skip the requested number of elements
   if (celt > length - mCurIndex) {
@@ -731,6 +797,8 @@ AccessibleEnumerator::Skip(unsigned long celt)
   }
   mCurIndex += celt;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 /**
@@ -753,6 +821,8 @@ AccessibleEnumerator::Skip(unsigned long celt)
 STDMETHODIMP
 AccessibleWrap::get_accSelection(VARIANT __RPC_FAR *pvarChildren)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarChildren)
     return E_INVALIDARG;
 
@@ -772,6 +842,8 @@ AccessibleWrap::get_accSelection(VARIANT __RPC_FAR *pvarChildren)
     NS_ADDREF(pvarChildren->punkVal = pEnum);
   }
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -779,6 +851,8 @@ AccessibleWrap::get_accDefaultAction(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszDefaultAction)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pszDefaultAction)
     return E_INVALIDARG;
 
@@ -800,6 +874,8 @@ AccessibleWrap::get_accDefaultAction(
   *pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
                                           defaultAction.Length());
   return *pszDefaultAction ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -807,6 +883,8 @@ AccessibleWrap::accSelect(
       /* [in] */ long flagsSelect,
       /* [optional][in] */ VARIANT varChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   RefPtr<IAccessible> accessible;
   HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
   if (FAILED(hr)) {
@@ -848,6 +926,8 @@ AccessibleWrap::accSelect(
   }
 
   return E_FAIL;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -858,6 +938,8 @@ AccessibleWrap::accLocation(
       /* [out] */ long __RPC_FAR *pcyHeight,
       /* [optional][in] */ VARIANT varChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pxLeft || !pyTop || !pcxWidth || !pcyHeight)
     return E_INVALIDARG;
 
@@ -884,6 +966,8 @@ AccessibleWrap::accLocation(
   *pcxWidth = rect.width;
   *pcyHeight = rect.height;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -892,6 +976,8 @@ AccessibleWrap::accNavigate(
       /* [optional][in] */ VARIANT varStart,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarEndUpAt)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarEndUpAt)
     return E_INVALIDARG;
 
@@ -974,6 +1060,8 @@ AccessibleWrap::accNavigate(
   pvarEndUpAt->pdispVal = NativeAccessible(navAccessible);
   pvarEndUpAt->vt = VT_DISPATCH;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -982,6 +1070,8 @@ AccessibleWrap::accHitTest(
       /* [in] */ long yTop,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!pvarChild)
     return E_INVALIDARG;
 
@@ -1008,12 +1098,16 @@ AccessibleWrap::accHitTest(
     return S_FALSE;
   }
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::accDoDefaultAction(
       /* [optional][in] */ VARIANT varChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   RefPtr<IAccessible> accessible;
   HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
   if (FAILED(hr)) {
@@ -1025,6 +1119,8 @@ AccessibleWrap::accDoDefaultAction(
   }
 
   return DoAction(0) ? S_OK : E_INVALIDARG;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
diff --git a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
index ec9d511e4..b78a8dd55 100644
--- a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -69,6 +69,8 @@ ApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appName(BSTR* aName)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aName)
     return E_INVALIDARG;
 
@@ -84,11 +86,15 @@ ApplicationAccessibleWrap::get_appName(BSTR* aName)
 
   *aName = ::SysAllocStringLen(name.get(), name.Length());
   return *aName ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appVersion(BSTR* aVersion)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aVersion)
     return E_INVALIDARG;
 
@@ -104,11 +110,15 @@ ApplicationAccessibleWrap::get_appVersion(BSTR* aVersion)
 
   *aVersion = ::SysAllocStringLen(version.get(), version.Length());
   return *aVersion ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_toolkitName(BSTR* aName)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aName)
     return E_INVALIDARG;
 
@@ -122,11 +132,15 @@ ApplicationAccessibleWrap::get_toolkitName(BSTR* aName)
 
   *aName = ::SysAllocStringLen(name.get(), name.Length());
   return *aName ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_toolkitVersion(BSTR* aVersion)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aVersion)
     return E_INVALIDARG;
 
@@ -142,5 +156,7 @@ ApplicationAccessibleWrap::get_toolkitVersion(BSTR* aVersion)
 
   *aVersion = ::SysAllocStringLen(version.get(), version.Length());
   return *aVersion ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
diff --git a/accessible/windows/msaa/DocAccessibleWrap.cpp b/accessible/windows/msaa/DocAccessibleWrap.cpp
index 895fe9192..6fb89816d 100644
--- a/accessible/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/windows/msaa/DocAccessibleWrap.cpp
@@ -65,6 +65,8 @@ DocAccessibleWrap::get_accParent(
 STDMETHODIMP
 DocAccessibleWrap::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aValue)
     return E_INVALIDARG;
   *aValue = nullptr;
@@ -88,6 +90,8 @@ DocAccessibleWrap::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue)
 
   *aValue = ::SysAllocStringLen(url.get(), url.Length());
   return *aValue ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/accessible/windows/msaa/EnumVariant.cpp b/accessible/windows/msaa/EnumVariant.cpp
index 2344208a3..86c81a105 100644
--- a/accessible/windows/msaa/EnumVariant.cpp
+++ b/accessible/windows/msaa/EnumVariant.cpp
@@ -21,6 +21,8 @@ STDMETHODIMP
 ChildrenEnumVariant::Next(ULONG aCount, VARIANT FAR* aItems,
                           ULONG FAR* aCountFetched)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aItems || !aCountFetched)
     return E_INVALIDARG;
 
@@ -53,11 +55,15 @@ ChildrenEnumVariant::Next(ULONG aCount, VARIANT FAR* aItems,
   (*aCountFetched) = countFetched;
 
   return countFetched < aCount ? S_FALSE : S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ChildrenEnumVariant::Skip(ULONG aCount)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (mAnchorAcc->IsDefunct() || mAnchorAcc->GetChildAt(mCurIndex) != mCurAcc)
     return CO_E_OBJNOTCONNECTED;
 
@@ -65,11 +71,15 @@ ChildrenEnumVariant::Skip(ULONG aCount)
   mCurAcc = mAnchorAcc->GetChildAt(mCurIndex);
 
   return mCurAcc ? S_OK : S_FALSE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ChildrenEnumVariant::Reset()
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (mAnchorAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -77,11 +87,15 @@ ChildrenEnumVariant::Reset()
   mCurAcc = mAnchorAcc->GetChildAt(0);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ChildrenEnumVariant::Clone(IEnumVARIANT** aEnumVariant)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aEnumVariant)
     return E_INVALIDARG;
 
@@ -89,4 +103,6 @@ ChildrenEnumVariant::Clone(IEnumVARIANT** aEnumVariant)
   (*aEnumVariant)->AddRef();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/msaa/IUnknownImpl.cpp b/accessible/windows/msaa/IUnknownImpl.cpp
index c74f86e33..4a9fa5383 100644
--- a/accessible/windows/msaa/IUnknownImpl.cpp
+++ b/accessible/windows/msaa/IUnknownImpl.cpp
@@ -37,5 +37,22 @@ GetHRESULT(nsresult aResult)
   }
 }
 
+int
+FilterExceptions(unsigned int aCode, EXCEPTION_POINTERS* aExceptionInfo)
+{
+  if (aCode == EXCEPTION_ACCESS_VIOLATION) {
+#ifdef MOZ_CRASHREPORTER
+    // MSAA swallows crashes (because it is COM-based) but we still need to
+    // learn about those crashes so we can fix them. Make sure to pass them to
+    // the crash reporter.
+    CrashReporter::WriteMinidumpForException(aExceptionInfo);
+#endif
+  } else {
+    NS_NOTREACHED("We should only be catching crash exceptions");
+  }
+
+  return EXCEPTION_CONTINUE_SEARCH;
+}
+
 } // namespace a11y
 } // namespace mozilla
diff --git a/accessible/windows/msaa/IUnknownImpl.h b/accessible/windows/msaa/IUnknownImpl.h
index d939a4dfa..dbf6c1374 100644
--- a/accessible/windows/msaa/IUnknownImpl.h
+++ b/accessible/windows/msaa/IUnknownImpl.h
@@ -79,6 +79,7 @@ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);              \
 STDMETHODIMP                                                                   \
 Class::QueryInterface(REFIID aIID, void** aInstancePtr)                        \
 {                                                                              \
+  A11Y_TRYBLOCK_BEGIN                                                          \
   if (!aInstancePtr)                                                           \
     return E_INVALIDARG;                                                       \
   *aInstancePtr = nullptr;                                                     \
@@ -87,14 +88,17 @@ Class::QueryInterface(REFIID aIID, void** aInstancePtr)                        \
 
 #define IMPL_IUNKNOWN_QUERY_TAIL                                               \
   return hr;                                                                   \
+  A11Y_TRYBLOCK_END                                                            \
 }
 
 #define IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(Member)                            \
   return Member->QueryInterface(aIID, aInstancePtr);                           \
+  A11Y_TRYBLOCK_END                                                            \
 }
 
 #define IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(BaseClass)                          \
   return BaseClass::QueryInterface(aIID, aInstancePtr);                        \
+  A11Y_TRYBLOCK_END                                                            \
 }
 
 #define IMPL_IUNKNOWN_QUERY_IFACE(Iface)                                       \
@@ -154,6 +158,21 @@ Class::QueryInterface(REFIID aIID, void** aInstancePtr)                        \
   IMPL_IUNKNOWN_QUERY_CLASS(Super2);                                           \
   IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0)
 
+
+/**
+ * Wrap every method body by these macroses to pass exception to the crash
+ * reporter.
+ */
+#define A11Y_TRYBLOCK_BEGIN                                                    \
+  MOZ_SEH_TRY {
+
+#define A11Y_TRYBLOCK_END                                                      \
+  } MOZ_SEH_EXCEPT(mozilla::a11y::FilterExceptions(::GetExceptionCode(),       \
+                                                   GetExceptionInformation())) \
+  { }                                                                          \
+  return E_FAIL;
+
+
 namespace mozilla {
 namespace a11y {
 
@@ -162,6 +181,11 @@ namespace a11y {
  */
 HRESULT GetHRESULT(nsresult aResult);
 
+/**
+ * Used to pass an exception to the crash reporter.
+ */
+int FilterExceptions(unsigned int aCode, EXCEPTION_POINTERS* aExceptionInfo);
+
 } // namespace a11y;
 } //namespace mozilla;
 
diff --git a/accessible/windows/sdn/sdnAccessible.cpp b/accessible/windows/sdn/sdnAccessible.cpp
index d90631c8f..909b0779c 100644
--- a/accessible/windows/sdn/sdnAccessible.cpp
+++ b/accessible/windows/sdn/sdnAccessible.cpp
@@ -28,6 +28,8 @@ using namespace mozilla::a11y;
 STDMETHODIMP
 sdnAccessible::QueryInterface(REFIID aREFIID, void** aInstancePtr)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aInstancePtr)
     return E_FAIL;
   *aInstancePtr = nullptr;
@@ -51,6 +53,8 @@ sdnAccessible::QueryInterface(REFIID aREFIID, void** aInstancePtr)
   }
 
   return E_NOINTERFACE;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -61,6 +65,8 @@ sdnAccessible::get_nodeInfo(BSTR __RPC_FAR* aNodeName,
                             unsigned int __RPC_FAR* aUniqueID,
                             unsigned short __RPC_FAR* aNodeType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNodeName || !aNameSpaceID || !aNodeValue || !aNumChildren ||
       !aUniqueID || !aNodeType)
     return E_INVALIDARG;
@@ -108,6 +114,8 @@ sdnAccessible::get_nodeInfo(BSTR __RPC_FAR* aNodeName,
   *aNumChildren = mNode->GetChildCount();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -117,6 +125,8 @@ sdnAccessible::get_attributes(unsigned  short aMaxAttribs,
                               BSTR __RPC_FAR* aAttribValues,
                               unsigned short __RPC_FAR* aNumAttribs)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAttribNames || !aNameSpaceIDs || !aAttribValues || !aNumAttribs)
     return E_INVALIDARG;
 
@@ -149,6 +159,8 @@ sdnAccessible::get_attributes(unsigned  short aMaxAttribs,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -157,6 +169,8 @@ sdnAccessible::get_attributesForNames(unsigned short aMaxAttribs,
                                       short __RPC_FAR* aNameSpaceID,
                                       BSTR __RPC_FAR* aAttribValues)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAttribNames || !aNameSpaceID || !aAttribValues)
     return E_INVALIDARG;
 
@@ -193,6 +207,8 @@ sdnAccessible::get_attributesForNames(unsigned short aMaxAttribs,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -202,6 +218,8 @@ sdnAccessible::get_computedStyle(unsigned short aMaxStyleProperties,
                                  BSTR __RPC_FAR* aStyleValues,
                                  unsigned short __RPC_FAR* aNumStyleProperties)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStyleProperties || aStyleValues || !aNumStyleProperties)
     return E_INVALIDARG;
 
@@ -239,6 +257,8 @@ sdnAccessible::get_computedStyle(unsigned short aMaxStyleProperties,
   *aNumStyleProperties = static_cast<unsigned short>(realIndex);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -247,6 +267,8 @@ sdnAccessible::get_computedStyleForProperties(unsigned short aNumStyleProperties
                                               BSTR __RPC_FAR* aStyleProperties,
                                               BSTR __RPC_FAR* aStyleValues)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aStyleProperties || !aStyleValues)
     return E_INVALIDARG;
 
@@ -269,11 +291,15 @@ sdnAccessible::get_computedStyleForProperties(unsigned short aNumStyleProperties
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::scrollTo(boolean aScrollTopLeft)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   DocAccessible* document = GetDocument();
   if (!document) // that's IsDefunct check
     return CO_E_OBJNOTCONNECTED;
@@ -287,11 +313,15 @@ sdnAccessible::scrollTo(boolean aScrollTopLeft)
 
   nsCoreUtils::ScrollTo(document->PresShell(), mNode->AsContent(), scrollType);
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -306,11 +336,15 @@ sdnAccessible::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -325,11 +359,15 @@ sdnAccessible::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -344,11 +382,15 @@ sdnAccessible::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -363,11 +405,15 @@ sdnAccessible::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -382,12 +428,16 @@ sdnAccessible::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_childAt(unsigned aChildIndex,
                            ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNode)
     return E_INVALIDARG;
   *aNode = nullptr;
@@ -403,11 +453,15 @@ sdnAccessible::get_childAt(unsigned aChildIndex,
 
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_innerHTML(BSTR __RPC_FAR* aInnerHTML)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aInnerHTML)
     return E_INVALIDARG;
   *aInnerHTML = nullptr;
@@ -428,11 +482,15 @@ sdnAccessible::get_innerHTML(BSTR __RPC_FAR* aInnerHTML)
     return E_OUTOFMEMORY;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_localInterface(void __RPC_FAR *__RPC_FAR* aLocalInterface)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLocalInterface)
     return E_INVALIDARG;
   *aLocalInterface = nullptr;
@@ -444,11 +502,15 @@ sdnAccessible::get_localInterface(void __RPC_FAR *__RPC_FAR* aLocalInterface)
   AddRef();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnAccessible::get_language(BSTR __RPC_FAR* aLanguage)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aLanguage)
     return E_INVALIDARG;
   *aLanguage = nullptr;
@@ -472,4 +534,6 @@ sdnAccessible::get_language(BSTR __RPC_FAR* aLanguage)
    return E_OUTOFMEMORY;
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/sdn/sdnDocAccessible.cpp b/accessible/windows/sdn/sdnDocAccessible.cpp
index a1c5be872..07b39e66f 100644
--- a/accessible/windows/sdn/sdnDocAccessible.cpp
+++ b/accessible/windows/sdn/sdnDocAccessible.cpp
@@ -24,6 +24,8 @@ IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mAccessible)
 STDMETHODIMP
 sdnDocAccessible::get_URL(BSTR __RPC_FAR* aURL)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aURL)
     return E_INVALIDARG;
   *aURL = nullptr;
@@ -38,11 +40,15 @@ sdnDocAccessible::get_URL(BSTR __RPC_FAR* aURL)
 
   *aURL = ::SysAllocStringLen(URL.get(), URL.Length());
   return *aURL ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::get_title(BSTR __RPC_FAR* aTitle)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aTitle)
     return E_INVALIDARG;
   *aTitle = nullptr;
@@ -54,11 +60,15 @@ sdnDocAccessible::get_title(BSTR __RPC_FAR* aTitle)
   mAccessible->Title(title);
   *aTitle = ::SysAllocStringLen(title.get(), title.Length());
   return *aTitle ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::get_mimeType(BSTR __RPC_FAR* aMimeType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aMimeType)
     return E_INVALIDARG;
   *aMimeType = nullptr;
@@ -73,11 +83,15 @@ sdnDocAccessible::get_mimeType(BSTR __RPC_FAR* aMimeType)
 
   *aMimeType = ::SysAllocStringLen(mimeType.get(), mimeType.Length());
   return *aMimeType ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::get_docType(BSTR __RPC_FAR* aDocType)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aDocType)
     return E_INVALIDARG;
   *aDocType = nullptr;
@@ -92,12 +106,16 @@ sdnDocAccessible::get_docType(BSTR __RPC_FAR* aDocType)
 
   *aDocType = ::SysAllocStringLen(docType.get(), docType.Length());
   return *aDocType ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::get_nameSpaceURIForID(short aNameSpaceID,
                                         BSTR __RPC_FAR* aNameSpaceURI)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aNameSpaceURI)
     return E_INVALIDARG;
   *aNameSpaceURI = nullptr;
@@ -120,14 +138,20 @@ sdnDocAccessible::get_nameSpaceURIForID(short aNameSpaceID,
                                        nameSpaceURI.Length());
 
   return *aNameSpaceURI ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::put_alternateViewMediaTypes(BSTR __RPC_FAR* aCommaSeparatedMediaTypes)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aCommaSeparatedMediaTypes)
     return E_INVALIDARG;
   *aCommaSeparatedMediaTypes = nullptr;
 
   return mAccessible->IsDefunct() ? CO_E_OBJNOTCONNECTED : E_NOTIMPL;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/accessible/windows/sdn/sdnTextAccessible.cpp b/accessible/windows/sdn/sdnTextAccessible.cpp
index b6f580ba3..b51caf44e 100644
--- a/accessible/windows/sdn/sdnTextAccessible.cpp
+++ b/accessible/windows/sdn/sdnTextAccessible.cpp
@@ -33,6 +33,8 @@ IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mAccessible)
 STDMETHODIMP
 sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aText)
     return E_INVALIDARG;
   *aText = nullptr;
@@ -49,6 +51,8 @@ sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText)
 
   *aText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -59,6 +63,8 @@ sdnTextAccessible::get_clippedSubstringBounds(unsigned int aStartIndex,
                                               int __RPC_FAR* aWidth,
                                               int __RPC_FAR* aHeight)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   nscoord x = 0, y = 0, width = 0, height = 0;
   HRESULT rv = get_unclippedSubstringBounds(aStartIndex, aEndIndex,
                                             &x, &y, &width, &height);
@@ -80,6 +86,8 @@ sdnTextAccessible::get_clippedSubstringBounds(unsigned int aStartIndex,
   *aWidth = clippedRect.width;
   *aHeight = clippedRect.height;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -90,6 +98,8 @@ sdnTextAccessible::get_unclippedSubstringBounds(unsigned int aStartIndex,
                                                 int __RPC_FAR* aWidth,
                                                 int __RPC_FAR* aHeight)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aX || !aY || !aWidth || !aHeight)
     return E_INVALIDARG;
   *aX = *aY = *aWidth = *aHeight = 0;
@@ -125,12 +135,16 @@ sdnTextAccessible::get_unclippedSubstringBounds(unsigned int aStartIndex,
   *aHeight = presContext->AppUnitsToDevPixels(sum.height);
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
                                      unsigned int aEndIndex)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (mAccessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -145,11 +159,15 @@ sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
     nsCoreUtils::ScrollSubstringTo(mAccessible->GetFrame(), range,
                                    nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
   return GetHRESULT(rv);
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR* aFontFamily)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aFontFamily)
     return E_INVALIDARG;
   *aFontFamily = nullptr;
@@ -171,6 +189,8 @@ sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR* aFontFamily)
 
   *aFontFamily = ::SysAllocStringLen(name.get(), name.Length());
   return *aFontFamily ? S_OK : E_OUTOFMEMORY;
+
+  A11Y_TRYBLOCK_END
 }
 
 nsIFrame*
diff --git a/accessible/windows/uia/uiaRawElmProvider.cpp b/accessible/windows/uia/uiaRawElmProvider.cpp
index 3121661e1..54e54766d 100644
--- a/accessible/windows/uia/uiaRawElmProvider.cpp
+++ b/accessible/windows/uia/uiaRawElmProvider.cpp
@@ -28,18 +28,24 @@ STDMETHODIMP
 uiaRawElmProvider::GetObjectForChild(long aIdChild,
                                      __RPC__deref_out_opt IAccessibleEx** aAccEx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAccEx)
     return E_INVALIDARG;
 
   *aAccEx = nullptr;
 
   return mAcc->IsDefunct() ? CO_E_OBJNOTCONNECTED : S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
                                       __RPC__out long* aIdChild)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aAcc || !aIdChild)
     return E_INVALIDARG;
 
@@ -54,11 +60,15 @@ uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
   mAcc->AddRef();
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetRuntimeId(__RPC__deref_out_opt SAFEARRAY** aRuntimeIds)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRuntimeIds)
     return E_INVALIDARG;
 
@@ -71,12 +81,16 @@ uiaRawElmProvider::GetRuntimeId(__RPC__deref_out_opt SAFEARRAY** aRuntimeIds)
     SafeArrayPutElement(*aRuntimeIds, &i, (void*)&(ids[i]));
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::ConvertReturnedElement(__RPC__in_opt IRawElementProviderSimple* aRawElmProvider,
                                           __RPC__deref_out_opt IAccessibleEx** aAccEx)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRawElmProvider || !aAccEx)
     return E_INVALIDARG;
 
@@ -88,6 +102,8 @@ uiaRawElmProvider::ConvertReturnedElement(__RPC__in_opt IRawElementProviderSimpl
     *aAccEx = static_cast<IAccessibleEx*>(instancePtr);
 
   return hr;
+
+  A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -96,29 +112,39 @@ uiaRawElmProvider::ConvertReturnedElement(__RPC__in_opt IRawElementProviderSimpl
 STDMETHODIMP
 uiaRawElmProvider::get_ProviderOptions(__RPC__out enum ProviderOptions* aOptions)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aOptions)
     return E_INVALIDARG;
 
   // This method is not used with IAccessibleEx implementations.
   *aOptions = ProviderOptions_ServerSideProvider;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetPatternProvider(PATTERNID aPatternId,
                                       __RPC__deref_out_opt IUnknown** aPatternProvider)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aPatternProvider)
     return E_INVALIDARG;
 
   *aPatternProvider = nullptr;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
                                     __RPC__out VARIANT* aPropertyValue)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aPropertyValue)
     return E_INVALIDARG;
 
@@ -200,15 +226,21 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
   }
 
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::get_HostRawElementProvider(__RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider)
 {
+  A11Y_TRYBLOCK_BEGIN
+
   if (!aRawElmProvider)
     return E_INVALIDARG;
 
   // This method is not used with IAccessibleEx implementations.
   *aRawElmProvider = nullptr;
   return S_OK;
+
+  A11Y_TRYBLOCK_END
 }
diff --git a/browser/app/basilisk.exe.manifest b/browser/app/basilisk.exe.manifest
index 079e15b58..bf5aac416 100644
--- a/browser/app/basilisk.exe.manifest
+++ b/browser/app/basilisk.exe.manifest
@@ -37,6 +37,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js
index a013dbd8a..81e7faf17 100644
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -201,16 +201,29 @@ let gDecoderDoctorHandler = {
   getLabelForNotificationBox(type) {
     if (type == "adobe-cdm-not-found" &&
         AppConstants.platform == "win") {
+      if (AppConstants.isPlatformAndVersionAtMost("win", "5.9")) {
+        // We supply our own Learn More button so we don't need to populate the message here.
+        return gNavigatorBundle.getFormattedString("emeNotifications.drmContentDisabled.message", [""]);
+      }
       return gNavigatorBundle.getString("decoder.noCodecs.message");
     }
     if (type == "adobe-cdm-not-activated" &&
         AppConstants.platform == "win") {
+      if (AppConstants.isPlatformAndVersionAtMost("win", "5.9")) {
+        return gNavigatorBundle.getString("decoder.noCodecsXP.message");
+      }
+      if (!AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) {
+        return gNavigatorBundle.getString("decoder.noCodecsVista.message");
+      }
       return gNavigatorBundle.getString("decoder.noCodecs.message");
     }
     if (type == "platform-decoder-not-found") {
-      if (AppConstants.platform == "win") {
+      if (AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) {
         return gNavigatorBundle.getString("decoder.noHWAcceleration.message");
       }
+      if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) {
+        return gNavigatorBundle.getString("decoder.noHWAccelerationVista.message");
+      }
       if (AppConstants.platform == "linux") {
         return gNavigatorBundle.getString("decoder.noCodecsLinux.message");
       }
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 910dc4f68..9ccd86b12 100755
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -97,6 +97,11 @@ XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
   return new scope.CustomizeMode(window);
 });
 
+XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
+  // Only show resizers on Windows 2000 and XP
+  return AppConstants.isPlatformAndVersionAtMost("win", "5.9");
+});
+
 XPCOMUtils.defineLazyGetter(this, "gPrefService", function() {
   return Services.prefs;
 });
@@ -3367,6 +3372,8 @@ var PrintPreviewListener = {
     this._chromeState.notificationsOpen = !notificationBox.notificationsHidden;
     notificationBox.notificationsHidden = true;
 
+    gBrowser.updateWindowResizers();
+
     this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden;
     if (gFindBarInitialized)
       gFindBar.close();
@@ -5215,6 +5222,7 @@ function setToolbarVisibility(toolbar, isVisible, persist=true) {
 
   PlacesToolbarHelper.init();
   BookmarkingUI.onToolbarVisibilityChange();
+  gBrowser.updateWindowResizers();
   if (isVisible)
     ToolbarIconColor.inferFromText();
 }
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index be17fb0e2..2c74aecdf 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -546,7 +546,9 @@
 #ifdef MENUBAR_CAN_AUTOHIDE
              toolbarname="&menubarCmd.label;"
              accesskey="&menubarCmd.accesskey;"
+#if defined(MOZ_WIDGET_GTK)
              autohide="true"
+#endif
 #endif
              context="toolbar-context-menu">
       <toolbaritem id="menubar-items" align="center">
diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml
index 0cb0f3bd6..3f4c3518e 100644
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -214,6 +214,18 @@
         ]]></body>
       </method>
 
+      <method name="updateWindowResizers">
+        <body><![CDATA[
+          if (!window.gShowPageResizers)
+            return;
+
+          var show = window.windowState == window.STATE_NORMAL;
+          for (let i = 0; i < this.browsers.length; i++) {
+            this.browsers[i].showWindowResizer = show;
+          }
+        ]]></body>
+      </method>
+
       <method name="_setCloseKeyState">
         <parameter name="aEnabled"/>
         <body><![CDATA[
@@ -1958,6 +1970,10 @@
               b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener);
             }
 
+            if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
+              b.setAttribute("showresizer", "true");
+            }
+
             if (!aParams.isPreloadBrowser && this.hasAttribute("autocompletepopup")) {
               b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
             }
@@ -4819,6 +4835,7 @@
           this.appendChild(this._autoScrollPopup);
           this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
           this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink;
+          this.updateWindowResizers();
 
           // Hook up the event listeners to the first browser
           var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true, false);
@@ -5837,6 +5854,8 @@
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
+
+              this.tabbrowser.updateWindowResizers();
               break;
             case "mouseout":
               // If the "related target" (the node to which the pointer went) is not
diff --git a/browser/base/jar.mn b/browser/base/jar.mn
index 3fa5ea408..60f1facc0 100644
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -8,6 +8,9 @@ browser.jar:
 %  overlay chrome://mozapps/content/update/updates.xul chrome://browser/content/softwareUpdateOverlay.xul
 %  overlay chrome://global/content/console.xul chrome://browser/content/jsConsoleOverlay.xul
 #endif
+#ifdef XP_WIN
+%  overlay chrome://browser/content/browser.xul chrome://browser/content/win6BrowserOverlay.xul os=WINNT osversion>=6
+#endif
 %  overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
 %  overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul
 
@@ -183,6 +186,9 @@ browser.jar:
 *       content/browser/webrtcIndicator.xul           (content/webrtcIndicator.xul)
         content/browser/webrtcIndicator.js            (content/webrtcIndicator.js)
 #endif
+#ifdef XP_WIN
+        content/browser/win6BrowserOverlay.xul        (content/win6BrowserOverlay.xul)
+#endif
 # the following files are browser-specific overrides
 *       content/browser/license.html                  (/toolkit/content/license.html)
 % override chrome://global/content/license.html chrome://browser/content/license.html
diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm
index 01389108d..86ff2708b 100644
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -262,14 +262,24 @@ var CustomizableUIInternal = {
       defaultCollapsed: false,
     }, true);
 
-    if (AppConstants.MENUBAR_CAN_AUTOHIDE) {
+    if (AppConstants.platform != "macosx") {
       this.registerArea(CustomizableUI.AREA_MENUBAR, {
         legacy: true,
         type: CustomizableUI.TYPE_TOOLBAR,
         defaultPlacements: [
           "menubar-items",
         ],
-        defaultCollapsed: true,
+        get defaultCollapsed() {
+          if (AppConstants.MENUBAR_CAN_AUTOHIDE) {
+            if (AppConstants.platform == "linux") {
+              return true;
+            }
+            // This is duplicated logic from /browser/base/jar.mn
+            // for win6BrowserOverlay.xul.
+            return AppConstants.isPlatformAndVersionAtLeast("win", 6);
+          }
+          return false;
+        }
       }, true);
     }
 
diff --git a/browser/components/shell/nsWindowsShellService.cpp b/browser/components/shell/nsWindowsShellService.cpp
index 879b0c7f0..cb13c0910 100644
--- a/browser/components/shell/nsWindowsShellService.cpp
+++ b/browser/components/shell/nsWindowsShellService.cpp
@@ -648,6 +648,11 @@ nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI()
 nsresult
 nsWindowsShellService::LaunchControlPanelDefaultPrograms()
 {
+  // This Default Programs feature is Win7+ only.
+  if (!IsWin7OrLater()) {
+    return NS_ERROR_FAILURE;
+  }
+
   // Build the path control.exe path safely
   WCHAR controlEXEPath[MAX_PATH + 1] = { '\0' };
   if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) {
diff --git a/browser/config/mozconfigs/win32/common-opt b/browser/config/mozconfigs/win32/common-opt
index 816c8926a..d43a9878b 100644
--- a/browser/config/mozconfigs/win32/common-opt
+++ b/browser/config/mozconfigs/win32/common-opt
@@ -4,6 +4,7 @@
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-jemalloc
+ac_add_options --enable-require-all-d3dc-versions
 
 if [ -f /c/builds/gapi.data ]; then
   _gapi_keyfile=c:/builds/gapi.data
diff --git a/browser/config/mozconfigs/win32/debug b/browser/config/mozconfigs/win32/debug
index 815276d0f..6beee93c2 100644
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -6,6 +6,7 @@ ac_add_options --enable-debug
 ac_add_options --enable-dmd
 ac_add_options --enable-profiling  # needed for --enable-dmd to work on Windows
 ac_add_options --enable-verify-mar
+ac_add_options --enable-require-all-d3dc-versions
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in
index ccfce3cd9..55df797ef 100644
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -61,6 +61,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/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index c2269c069..bddca2f29 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -607,6 +607,10 @@
 #ifdef MOZ_D3DCOMPILER_VISTA_DLL
 @BINPATH@/@MOZ_D3DCOMPILER_VISTA_DLL@
 #endif
+
+#ifdef MOZ_D3DCOMPILER_XP_DLL
+@BINPATH@/@MOZ_D3DCOMPILER_XP_DLL@
+#endif
 #endif # MOZ_ANGLE_RENDERER
 
 ; [Browser Chrome Files]
diff --git a/browser/installer/windows/nsis/defines.nsi.in b/browser/installer/windows/nsis/defines.nsi.in
index 5ad9b7966..d0f0c443a 100644
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -63,7 +63,7 @@
 !define MinSupportedVer "Microsoft Windows 7 x64"
 #else
 !define ARCH "x86"
-!define MinSupportedVer "Microsoft Windows 7"
+!define MinSupportedVer "Microsoft Windows XP SP2"
 #endif
 
 !define MinSupportedCPU "SSE2"
diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties
index 6f3aab397..1947a3c90 100644
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -731,8 +731,11 @@ pendingCrashReports.alwaysSend = Always Send
 decoder.noCodecs.button = Learn how
 decoder.noCodecs.accesskey = L
 decoder.noCodecs.message = To play video, you may need to install Microsoft’s Media Feature Pack.
+decoder.noCodecsVista.message = To play video, you may need to install Microsoft’s Platform Update Supplement for Windows Vista.
+decoder.noCodecsXP.message = To play video, you may need to enable Adobe’s Primetime Content Decryption Module.
 decoder.noCodecsLinux.message = To play video, you may need to install the required video codecs.
 decoder.noHWAcceleration.message = To improve video quality, you may need to install Microsoft’s Media Feature Pack.
+decoder.noHWAccelerationVista.message = To improve video quality, you may need to install Microsoft’s Platform Update Supplement for Windows Vista.
 decoder.noPulseAudio.message = To play audio, you may need to install the required PulseAudio software.
 decoder.unsupportedLibavcodec.message = libavcodec may be vulnerable or is not supported, and should be updated to play video.
 
diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure
index b33f18623..f7877f96f 100644
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -218,6 +218,7 @@ def old_configure_options(*options):
     '--enable-readline',
     '--enable-reflow-perf',
     '--enable-release',
+    '--enable-require-all-d3dc-versions',
     '--enable-safe-browsing',
     '--enable-sandbox',
     '--enable-signmar',
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/angle/moz.build b/gfx/angle/moz.build
index 2a40e0ac6..1da8356a5 100755
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -139,6 +139,9 @@ if CONFIG['GNU_CXX']:
             '-Wno-shadow-local',
         ]
 
+if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+    LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
diff --git a/gfx/angle/src/libANGLE/moz.build b/gfx/angle/src/libANGLE/moz.build
index e127ccce1..0a2a4437f 100755
--- a/gfx/angle/src/libANGLE/moz.build
+++ b/gfx/angle/src/libANGLE/moz.build
@@ -353,6 +353,9 @@ if CONFIG['GNU_CXX']:
             '-Wno-shadow-local',
         ]
 
+if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+    LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
@@ -385,6 +388,11 @@ DEFINES['ANGLE_DEFAULT_D3D11'] = "0"
 
 if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
   OS_LIBS += [ 'd3d9', 'dxguid' ]
+else:
+  EXTRA_DSO_LDOPTS += [
+    '\'%s/lib/%s/d3d9.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+    '\'%s/lib/%s/dxguid.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+  ]
 
 Library('libANGLE')
 
diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build
index c1e33c86e..8e99d44ff 100755
--- a/gfx/angle/src/libEGL/moz.build
+++ b/gfx/angle/src/libEGL/moz.build
@@ -32,6 +32,9 @@ if CONFIG['GNU_CXX']:
             '-Wno-shadow-local',
         ]
 
+if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+    LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
@@ -64,6 +67,11 @@ DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
 
 if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
   OS_LIBS += [ 'd3d9', 'dxguid' ]
+else:
+  EXTRA_DSO_LDOPTS += [
+    '\'%s/lib/%s/d3d9.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+    '\'%s/lib/%s/dxguid.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+  ]
 
 
 GeckoSharedLibrary('libEGL', linkage=None)
diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build
index 08c60c213..1d40b3b67 100755
--- a/gfx/angle/src/libGLESv2/moz.build
+++ b/gfx/angle/src/libGLESv2/moz.build
@@ -39,6 +39,9 @@ if CONFIG['GNU_CXX']:
             '-Wno-shadow-local',
         ]
 
+if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+    LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
@@ -70,6 +73,11 @@ DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
 
 if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
   OS_LIBS += [ 'd3d9', 'dxguid' ]
+else:
+  EXTRA_DSO_LDOPTS += [
+    '\'%s/lib/%s/d3d9.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+    '\'%s/lib/%s/dxguid.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+  ]
 
 GeckoSharedLibrary('libGLESv2', linkage=None)
 
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/gfxGDIFont.cpp b/gfx/thebes/gfxGDIFont.cpp
index d6e98105c..e6ceeaf6d 100644
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -461,7 +461,8 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize,
         weight = mNeedsBold ? 700 : fe->Weight();
     }
 
-    fe->FillLogFont(&aLogFont, weight, aSize);
+    fe->FillLogFont(&aLogFont, weight, aSize, 
+                    (mAntialiasOption == kAntialiasSubpixel) ? true : false);
 
     // If GDI synthetic italic is wanted, force the lfItalic field to true
     if (aUseGDIFakeItalic) {
diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp
index cc047ef38..d80c49356 100644
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -37,6 +37,11 @@ using namespace mozilla;
 
 #define ROUND(x) floor((x) + 0.5)
 
+
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+
 #define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
                                LogLevel::Debug, args)
 #define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
@@ -217,7 +222,16 @@ GDIFontEntry::IsSymbolFont()
 gfxFont *
 GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold)
 {
-    return new gfxGDIFont(this, aFontStyle, aNeedsBold);
+    bool isXP = !IsVistaOrLater();
+
+    bool useClearType = isXP && !aFontStyle->systemFont &&
+        (gfxWindowsPlatform::GetPlatform()->UseClearTypeAlways() ||
+         (mIsDataUserFont &&
+          gfxWindowsPlatform::GetPlatform()->UseClearTypeForDownloadableFonts()));
+
+    return new gfxGDIFont(this, aFontStyle, aNeedsBold, 
+                          (useClearType ? gfxFont::kAntialiasSubpixel
+                                        : gfxFont::kAntialiasDefault));
 }
 
 nsresult
@@ -249,7 +263,8 @@ GDIFontEntry::CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer)
 
 void
 GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
-                          uint16_t aWeight, gfxFloat aSize)
+                          uint16_t aWeight, gfxFloat aSize,
+                          bool aUseCleartype)
 {
     memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
 
@@ -275,6 +290,8 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
     if (mIsDataUserFont) {
         aLogFont->lfItalic = 0;
     }
+
+    aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY);
 }
 
 #define MISSING_GLYPH 0x1F // glyph index returned for missing characters
@@ -862,8 +879,15 @@ gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
         gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
         aStyle, w, aStretch, winUserFontData, false);
 
-    if (fe) {
-      fe->mIsDataUserFont = true;
+    if (!fe)
+        return fe;
+
+    fe->mIsDataUserFont = true;
+
+    // Uniscribe doesn't place CFF fonts loaded privately
+    // via AddFontMemResourceEx on XP/Vista
+    if (isCFF && !IsWin7OrLater()) {
+        fe->mForceGDI = true;
     }
 
     return fe;
diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h
index 60fb292e8..ffb513d64 100644
--- a/gfx/thebes/gfxGDIFontList.h
+++ b/gfx/thebes/gfxGDIFontList.h
@@ -112,7 +112,8 @@ public:
 
     virtual bool IsSymbolFont();
 
-    void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize);
+    void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize,
+                     bool aUseCleartype);
 
     static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, 
                                                 DWORD fontType)
diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
index 84199170b..be1780797 100755
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -146,6 +146,9 @@ public:
 
 NS_IMPL_ISUPPORTS(GfxD2DVramReporter, nsIMemoryReporter)
 
+#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
+#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
+
 #define GFX_CLEARTYPE_PARAMS           "gfx.font_rendering.cleartype_params."
 #define GFX_CLEARTYPE_PARAMS_GAMMA     "gfx.font_rendering.cleartype_params.gamma"
 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
@@ -191,6 +194,10 @@ public:
         HMODULE gdi32Handle;
         PFND3DKMTQS queryD3DKMTStatistics = nullptr;
 
+        // GPU memory reporting is not available before Windows 7
+        if (!IsWin7OrLater())
+            return NS_OK;
+
         if ((gdi32Handle = LoadLibrary(TEXT("gdi32.dll"))))
             queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics");
 
@@ -313,6 +320,9 @@ NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
 {
+  mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
+  mUseClearTypeAlways = UNINITIALIZED_VALUE;
+
   /*
    * Initialize COM
    */
@@ -392,6 +402,10 @@ gfxWindowsPlatform::CanUseHardwareVideoDecoding()
 bool
 gfxWindowsPlatform::InitDWriteSupport()
 {
+  if (!IsVistaOrLater()) {
+    return false;
+  }
+
   // DWrite is only supported on Windows 7 with the platform update and higher.
   // We check this by seeing if D2D1 support is available.
   if (!Factory::SupportsD2D1()) {
@@ -983,6 +997,26 @@ gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
 #endif // _WIN32
 }
 
+bool
+gfxWindowsPlatform::UseClearTypeForDownloadableFonts()
+{
+    if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) {
+        mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true);
+    }
+
+    return mUseClearTypeForDownloadableFonts;
+}
+
+bool
+gfxWindowsPlatform::UseClearTypeAlways()
+{
+    if (mUseClearTypeAlways == UNINITIALIZED_VALUE) {
+        mUseClearTypeAlways = Preferences::GetBool(GFX_USE_CLEARTYPE_ALWAYS, false);
+    }
+
+    return mUseClearTypeAlways;
+}
+
 void
 gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion)
 {
@@ -1126,7 +1160,14 @@ gfxWindowsPlatform::FontsPrefsChanged(const char *aPref)
 
     gfxPlatform::FontsPrefsChanged(aPref);
 
-    if (aPref && !strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
+    if (!aPref) {
+        mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
+        mUseClearTypeAlways = UNINITIALIZED_VALUE;
+    } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, aPref)) {
+        mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
+    } else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
+        mUseClearTypeAlways = UNINITIALIZED_VALUE;
+    } else if (!strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
         SetupClearTypeParams();
     } else {
         clearTextFontCaches = false;
@@ -1374,13 +1415,17 @@ gfxWindowsPlatform::InitializeD3D9Config()
     return;
   }
 
-  d3d9.SetDefaultFromPref(
-    gfxPrefs::GetLayersAllowD3D9FallbackPrefName(),
-    true,
-    gfxPrefs::GetLayersAllowD3D9FallbackPrefDefault());
+  if (!IsVistaOrLater()) {
+    d3d9.EnableByDefault();
+  } else {
+    d3d9.SetDefaultFromPref(
+      gfxPrefs::GetLayersAllowD3D9FallbackPrefName(),
+      true,
+      gfxPrefs::GetLayersAllowD3D9FallbackPrefDefault());
 
-  if (!d3d9.IsEnabled() && gfxPrefs::LayersPreferD3D9()) {
-    d3d9.UserEnable("Direct3D9 enabled via layers.prefer-d3d9");
+    if (!d3d9.IsEnabled() && gfxPrefs::LayersPreferD3D9()) {
+      d3d9.UserEnable("Direct3D9 enabled via layers.prefer-d3d9");
+    }
   }
 
   nsCString message;
@@ -1551,6 +1596,11 @@ gfxWindowsPlatform::InitializeD2DConfig()
                           NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_D3D11_COMP"));
     return;
   }
+  if (!IsVistaOrLater()) {
+    d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D is not available on Windows XP",
+                          NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_XP"));
+    return;
+  }
 
   d2d1.SetDefaultFromPref(
     gfxPrefs::GetDirect2DDisabledPrefName(),
@@ -1642,12 +1692,14 @@ gfxWindowsPlatform::InitGPUProcessSupport()
       "Not using GPU Process since D3D11 is unavailable",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_D3D11"));
   } else if (!IsWin7SP1OrLater()) {
-    // On Windows 7 Pre-SP1, DXGI 1.2 is not available and remote presentation
-    // for D3D11 will not work. Rather than take a regression and use D3D9, we
-    // revert back to in-process rendering.
+    // For Windows XP, we simply don't care enough to support this
+    // configuration. On Windows Vista and 7 Pre-SP1, DXGI 1.2 is not
+    // available and remote presentation for D3D11 will not work. Rather
+    // than take a regression and use D3D9, we revert back to in-process
+    // rendering.
     gpuProc.Disable(
       FeatureStatus::Unavailable,
-      "Windows 7 Pre-SP1 cannot use the GPU process",
+      "Windows XP, Vista, and 7 Pre-SP1 cannot use the GPU process",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_OLD_WINDOWS"));
   } else if (!IsWin8OrLater()) {
     // Windows 7 SP1 can have DXGI 1.2 only via the Platform Update, so we
@@ -1670,6 +1722,10 @@ gfxWindowsPlatform::InitGPUProcessSupport()
 bool
 gfxWindowsPlatform::DwmCompositionEnabled()
 {
+  if (!IsVistaOrLater()) {
+    return false;
+  }
+
   MOZ_ASSERT(WinUtils::dwmIsCompositionEnabledPtr);
   BOOL dwmEnabled = false;
 
diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h
index f77d9a87a..8db7cf575 100644
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -184,6 +184,11 @@ public:
 
     mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override;
 
+    // ClearType is not always enabled even when available (e.g. Windows XP)
+    // if either of these prefs are enabled and apply, use ClearType rendering
+    bool UseClearTypeForDownloadableFonts();
+    bool UseClearTypeAlways();
+
     static void GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion);
 
     // returns ClearType tuning information for each display
@@ -242,6 +247,9 @@ protected:
 protected:
     RenderMode mRenderMode;
 
+    int8_t mUseClearTypeForDownloadableFonts;
+    int8_t mUseClearTypeAlways;
+
 private:
     void Init();
     void InitAcceleration() override;
diff --git a/hal/windows/WindowsBattery.cpp b/hal/windows/WindowsBattery.cpp
index 520330242..c1b9a31e6 100644
--- a/hal/windows/WindowsBattery.cpp
+++ b/hal/windows/WindowsBattery.cpp
@@ -5,20 +5,45 @@
 
 #include "Hal.h"
 #include "HalImpl.h"
+#include "nsITimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/battery/Constants.h"
+#include "nsComponentManagerUtils.h"
 
 #include <windows.h>
+#include "mozilla/WindowsVersion.h"
 
 using namespace mozilla::dom::battery;
 
 namespace mozilla {
 namespace hal_impl {
 
+static nsCOMPtr<nsITimer> sUpdateTimer;
+
+/* Power Event API is Vista or later */
+static decltype(RegisterPowerSettingNotification)* sRegisterPowerSettingNotification = nullptr;
+static decltype(UnregisterPowerSettingNotification)* sUnregisterPowerSettingNotification = nullptr;
 static HPOWERNOTIFY sPowerHandle = nullptr;
 static HPOWERNOTIFY sCapacityHandle = nullptr;
 static HWND sHWnd = nullptr;
 
+static void
+UpdateHandler(nsITimer* aTimer, void* aClosure) {
+  NS_ASSERTION(!IsVistaOrLater(),
+               "We shouldn't call this function for Vista or later version!");
+
+  static hal::BatteryInformation sLastInfo;
+  hal::BatteryInformation currentInfo;
+
+  hal_impl::GetCurrentBatteryInformation(&currentInfo);
+  if (sLastInfo.level() != currentInfo.level() ||
+      sLastInfo.charging() != currentInfo.charging() ||
+      sLastInfo.remainingTime() != currentInfo.remainingTime()) {
+    hal::NotifyBatteryChange(currentInfo);
+    sLastInfo = currentInfo;
+  }
+}
+
 static
 LRESULT CALLBACK
 BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
@@ -38,56 +63,94 @@ BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
 void
 EnableBatteryNotifications()
 {
-  // Create custom window to watch battery event
-  // If we can get Gecko's window handle, this is unnecessary.
-
-  if (sHWnd == nullptr) {
-    WNDCLASSW wc;
-    HMODULE hSelf = GetModuleHandle(nullptr);
-
-    if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
-      ZeroMemory(&wc, sizeof(WNDCLASSW));
-      wc.hInstance = hSelf;
-      wc.lpfnWndProc = BatteryWindowProc;
-      wc.lpszClassName = L"MozillaBatteryClass";
-      RegisterClassW(&wc);
+  if (IsVistaOrLater()) {
+    // RegisterPowerSettingNotification is from Vista or later.
+    // Use this API if available.
+    HMODULE hUser32 = GetModuleHandleW(L"USER32.DLL");
+    if (!sRegisterPowerSettingNotification)
+      sRegisterPowerSettingNotification = (decltype(RegisterPowerSettingNotification)*)
+        GetProcAddress(hUser32, "RegisterPowerSettingNotification");
+    if (!sUnregisterPowerSettingNotification)
+      sUnregisterPowerSettingNotification = (decltype(UnregisterPowerSettingNotification)*)
+        GetProcAddress(hUser32, "UnregisterPowerSettingNotification");
+
+    if (!sRegisterPowerSettingNotification ||
+        !sUnregisterPowerSettingNotification) {
+      NS_ASSERTION(false, "Canot find PowerSettingNotification functions.");
+      return;
     }
 
-    sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
-                          0, 0, 0, 0, 0,
-                          nullptr, nullptr, hSelf, nullptr);
-  }
+    // Create custom window to watch battery event
+    // If we can get Gecko's window handle, this is unnecessary.
 
-  if (sHWnd == nullptr) {
-    return;
-  }
+    if (sHWnd == nullptr) {
+      WNDCLASSW wc;
+      HMODULE hSelf = GetModuleHandle(nullptr);
+
+      if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
+        ZeroMemory(&wc, sizeof(WNDCLASSW));
+        wc.hInstance = hSelf;
+        wc.lpfnWndProc = BatteryWindowProc;
+        wc.lpszClassName = L"MozillaBatteryClass";
+        RegisterClassW(&wc);
+      }
 
-  sPowerHandle =
-    RegisterPowerSettingNotification(sHWnd,
-                                     &GUID_ACDC_POWER_SOURCE,
-                                     DEVICE_NOTIFY_WINDOW_HANDLE);
-  sCapacityHandle =
-    RegisterPowerSettingNotification(sHWnd,
-                                     &GUID_BATTERY_PERCENTAGE_REMAINING,
-                                     DEVICE_NOTIFY_WINDOW_HANDLE);
+      sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
+                            0, 0, 0, 0, 0,
+                            nullptr, nullptr, hSelf, nullptr);
+    }
+
+    if (sHWnd == nullptr) {
+      return;
+    }
+
+    sPowerHandle =
+      sRegisterPowerSettingNotification(sHWnd,
+                                        &GUID_ACDC_POWER_SOURCE,
+                                        DEVICE_NOTIFY_WINDOW_HANDLE);
+    sCapacityHandle =
+      sRegisterPowerSettingNotification(sHWnd,
+                                        &GUID_BATTERY_PERCENTAGE_REMAINING,
+                                        DEVICE_NOTIFY_WINDOW_HANDLE);
+  } else
+  {
+    // for Windows XP.  If we remove Windows XP support,
+    // we should remove timer-based power notification
+    sUpdateTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    if (sUpdateTimer) {
+      sUpdateTimer->InitWithFuncCallback(UpdateHandler,
+                                         nullptr,
+                                         Preferences::GetInt("dom.battery.timer",
+                                                             30000 /* 30s */),
+                                         nsITimer::TYPE_REPEATING_SLACK);
+    } 
+  }
 }
 
 void
 DisableBatteryNotifications()
 {
-  if (sPowerHandle) {
-    UnregisterPowerSettingNotification(sPowerHandle);
-    sPowerHandle = nullptr;
-  }
+  if (IsVistaOrLater()) {
+    if (sPowerHandle) {
+      sUnregisterPowerSettingNotification(sPowerHandle);
+      sPowerHandle = nullptr;
+    }
 
-  if (sCapacityHandle) {
-    UnregisterPowerSettingNotification(sCapacityHandle);
-    sCapacityHandle = nullptr;
-  }
+    if (sCapacityHandle) {
+      sUnregisterPowerSettingNotification(sCapacityHandle);
+      sCapacityHandle = nullptr;
+    }
 
-  if (sHWnd) {
-    DestroyWindow(sHWnd);
-    sHWnd = nullptr;
+    if (sHWnd) {
+      DestroyWindow(sHWnd);
+      sHWnd = nullptr;
+    }
+  } else
+  {
+    if (sUpdateTimer) {
+      sUpdateTimer->Cancel();
+      sUpdateTimer = nullptr;
+    }
   }
 }
 
diff --git a/image/decoders/icon/win/nsIconChannel.cpp b/image/decoders/icon/win/nsIconChannel.cpp
index 04680627a..9ddcbbc48 100644
--- a/image/decoders/icon/win/nsIconChannel.cpp
+++ b/image/decoders/icon/win/nsIconChannel.cpp
@@ -29,6 +29,11 @@
 #include "nsContentSecurityManager.h"
 #include "nsContentUtils.h"
 
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0600
+
 // we need windows.h to read out registry information...
 #include <windows.h>
 #include <shellapi.h>
@@ -411,27 +416,41 @@ nsIconChannel::GetStockHIcon(nsIMozIconURI* aIconURI,
 {
   nsresult rv = NS_OK;
 
-  uint32_t desiredImageSize;
-  aIconURI->GetImageSize(&desiredImageSize);
-  nsAutoCString stockIcon;
-  aIconURI->GetStockIcon(stockIcon);
-
-  SHSTOCKICONID stockIconID = GetStockIconIDForName(stockIcon);
-  if (stockIconID == SIID_INVALID) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
+  // We can only do this on Vista or above
+  HMODULE hShellDLL = ::LoadLibraryW(L"shell32.dll");
+  decltype(SHGetStockIconInfo)* pSHGetStockIconInfo =
+    (decltype(SHGetStockIconInfo)*) ::GetProcAddress(hShellDLL,
+                                                    "SHGetStockIconInfo");
+
+  if (pSHGetStockIconInfo) {
+    uint32_t desiredImageSize;
+    aIconURI->GetImageSize(&desiredImageSize);
+    nsAutoCString stockIcon;
+    aIconURI->GetStockIcon(stockIcon);
+
+    SHSTOCKICONID stockIconID = GetStockIconIDForName(stockIcon);
+    if (stockIconID == SIID_INVALID) {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
 
-  UINT infoFlags = SHGSI_ICON;
-  infoFlags |= GetSizeInfoFlag(desiredImageSize);
+    UINT infoFlags = SHGSI_ICON;
+    infoFlags |= GetSizeInfoFlag(desiredImageSize);
 
-  SHSTOCKICONINFO sii = {0};
-  sii.cbSize = sizeof(sii);
-  HRESULT hr = SHGetStockIconInfo(stockIconID, infoFlags, &sii);
+    SHSTOCKICONINFO sii = {0};
+    sii.cbSize = sizeof(sii);
+    HRESULT hr = pSHGetStockIconInfo(stockIconID, infoFlags, &sii);
 
-  if (SUCCEEDED(hr)) {
-    *hIcon = sii.hIcon;
+    if (SUCCEEDED(hr)) {
+      *hIcon = sii.hIcon;
+    } else {
+      rv = NS_ERROR_FAILURE;
+    }
   } else {
-    rv = NS_ERROR_FAILURE;
+    rv = NS_ERROR_NOT_AVAILABLE;
+  }
+
+  if (hShellDLL) {
+    ::FreeLibrary(hShellDLL);
   }
 
   return rv;
diff --git a/ipc/app/plugin-container.exe.manifest b/ipc/app/plugin-container.exe.manifest
index 303109523..d61ddec1a 100644
--- a/ipc/app/plugin-container.exe.manifest
+++ b/ipc/app/plugin-container.exe.manifest
@@ -37,6 +37,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/ipc/chromium/src/base/process_util_win.cc b/ipc/chromium/src/base/process_util_win.cc
index f22f7216f..12fbc23a5 100644
--- a/ipc/chromium/src/base/process_util_win.cc
+++ b/ipc/chromium/src/base/process_util_win.cc
@@ -297,6 +297,43 @@ bool LaunchApp(const std::wstring& cmdline,
   startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW;
 
   LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
+  // Don't even bother trying pre-Vista...
+  if (mozilla::IsVistaOrLater()) {
+    // setup our handle array first - if we end up with no handles that can
+    // be inherited we can avoid trying to do the ThreadAttributeList dance...
+    HANDLE handlesToInherit[2];
+    int handleCount = 0;
+    HANDLE stdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
+    HANDLE stdErr = ::GetStdHandle(STD_ERROR_HANDLE);
+
+    if (IsInheritableHandle(stdOut))
+      handlesToInherit[handleCount++] = stdOut;
+    if (stdErr != stdOut && IsInheritableHandle(stdErr))
+      handlesToInherit[handleCount++] = stdErr;
+
+    if (handleCount) {
+      lpAttributeList = CreateThreadAttributeList(handlesToInherit, handleCount);
+      if (lpAttributeList) {
+        // it's safe to inherit handles, so arrange for that...
+        startup_info.cb = sizeof(startup_info_ex);
+        startup_info.dwFlags |= STARTF_USESTDHANDLES;
+        startup_info.hStdOutput = stdOut;
+        startup_info.hStdError = stdErr;
+        startup_info.hStdInput = INVALID_HANDLE_VALUE;
+        startup_info_ex.lpAttributeList = lpAttributeList;
+        dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
+        bInheritHandles = TRUE;
+      }
+    }
+  } else if (PR_GetEnv("MOZ_WIN_INHERIT_STD_HANDLES_PRE_VISTA")) {
+    // Even if we can't limit what gets inherited, we sometimes want to inherit
+    // stdout/err for testing purposes.
+    startup_info.dwFlags |= STARTF_USESTDHANDLES;
+    startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+    startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+    startup_info.hStdInput = INVALID_HANDLE_VALUE;
+    bInheritHandles = TRUE;
+  }
 
   PROCESS_INFORMATION process_info;
   BOOL createdOK = CreateProcess(NULL,
diff --git a/ipc/glue/WindowsMessageLoop.cpp b/ipc/glue/WindowsMessageLoop.cpp
index 8f3471efc..8057ee25d 100644
--- a/ipc/glue/WindowsMessageLoop.cpp
+++ b/ipc/glue/WindowsMessageLoop.cpp
@@ -1034,7 +1034,7 @@ MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
   MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!");
 
 #if defined(ACCESSIBILITY)
-  if (mFlags & REQUIRE_A11Y_REENTRY) {
+  if (IsVistaOrLater() && (mFlags & REQUIRE_A11Y_REENTRY)) {
     MOZ_ASSERT(!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION));
     return WaitForSyncNotifyWithA11yReentry();
   }
diff --git a/ipc/mscom/MainThreadRuntime.cpp b/ipc/mscom/MainThreadRuntime.cpp
index a061eaf54..d86317966 100644
--- a/ipc/mscom/MainThreadRuntime.cpp
+++ b/ipc/mscom/MainThreadRuntime.cpp
@@ -44,6 +44,13 @@ MainThreadRuntime::MainThreadRuntime()
     return;
   }
 
+  // Windows XP doesn't support setting of the COM exception policy, so we'll
+  // just stop here in that case.
+  if (!IsVistaOrLater()) {
+    mInitResult = S_OK;
+    return;
+  }
+
   // We are required to initialize security in order to configure global options.
   mInitResult = InitializeSecurity();
   MOZ_ASSERT(SUCCEEDED(mInitResult));
@@ -60,8 +67,11 @@ MainThreadRuntime::MainThreadRuntime()
     return;
   }
 
-  // Use the strictest policy available.
-  ULONG_PTR exceptionSetting = COMGLB_EXCEPTION_DONOT_HANDLE_ANY;
+  // Windows 7 has a policy that is even more strict. We should use that one
+  // whenever possible.
+  ULONG_PTR exceptionSetting = IsWin7OrLater() ?
+                               COMGLB_EXCEPTION_DONOT_HANDLE_ANY :
+                               COMGLB_EXCEPTION_DONOT_HANDLE;
   mInitResult = globalOpts->Set(COMGLB_EXCEPTION_HANDLING, exceptionSetting);
   MOZ_ASSERT(SUCCEEDED(mInitResult));
 }
diff --git a/js/src/jsutil.cpp b/js/src/jsutil.cpp
index 705d21975..bb9f33df9 100644
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -39,7 +39,7 @@ mozilla::Atomic<AutoEnterOOMUnsafeRegion*> AutoEnterOOMUnsafeRegion::owner_;
 namespace oom {
 
 JS_PUBLIC_DATA(uint32_t) targetThread = 0;
-MOZ_THREAD_LOCAL(uint32_t) threadType;
+JS_PUBLIC_DATA(MOZ_THREAD_LOCAL(uint32_t)) threadType;
 JS_PUBLIC_DATA(uint64_t) maxAllocations = UINT64_MAX;
 JS_PUBLIC_DATA(uint64_t) counter = 0;
 JS_PUBLIC_DATA(bool) failAlways = true;
diff --git a/js/src/old-configure.in b/js/src/old-configure.in
index 5da81ce3e..94ecc5fd7 100644
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -143,7 +143,8 @@ MOZ_TOOL_VARIABLES
 dnl Special win32 checks
 dnl ========================================================
 
-WINVER=601
+# Target the Windows 8.1 SDK by default
+WINVER=502
 
 case "$target" in
 *-mingw*)
@@ -721,7 +722,12 @@ case "$target" in
         IMPORT_LIB_SUFFIX=lib
         MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        WIN32_SUBSYSTEM_VERSION=6.01
+        dnl Set subsystem version 5 for Windows XP.
+        if test "$CPU_ARCH" = "x86"; then
+            WIN32_SUBSYSTEM_VERSION=5.01
+        else
+            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
diff --git a/js/src/threading/windows/ConditionVariable.cpp b/js/src/threading/windows/ConditionVariable.cpp
index 3c75a0f27..868c35141 100644
--- a/js/src/threading/windows/ConditionVariable.cpp
+++ b/js/src/threading/windows/ConditionVariable.cpp
@@ -28,34 +28,342 @@
   _InterlockedIncrement((volatile long*)(addend))
 #endif
 
+// Windows XP and Server 2003 don't support condition variables natively. The
+// NativeImports class is responsible for detecting native support and
+// retrieving the appropriate function pointers. It gets instantiated once,
+// using a static initializer.
+class ConditionVariableNativeImports
+{
+public:
+  ConditionVariableNativeImports() {
+    HMODULE kernel32_dll = GetModuleHandle("kernel32.dll");
+    MOZ_RELEASE_ASSERT(kernel32_dll != NULL);
+
+#define LOAD_SYMBOL(symbol) loadSymbol(kernel32_dll, #symbol, symbol)
+    supported_ = LOAD_SYMBOL(InitializeConditionVariable) &&
+                 LOAD_SYMBOL(WakeConditionVariable) &&
+                 LOAD_SYMBOL(WakeAllConditionVariable) &&
+                 LOAD_SYMBOL(SleepConditionVariableCS);
+#undef LOAD_SYMBOL
+  }
+
+  inline bool supported() const {
+    return supported_;
+  }
+
+  void(WINAPI* InitializeConditionVariable)(CONDITION_VARIABLE* ConditionVariable);
+  void(WINAPI* WakeAllConditionVariable)(PCONDITION_VARIABLE ConditionVariable);
+  void(WINAPI* WakeConditionVariable)(CONDITION_VARIABLE* ConditionVariable);
+  BOOL(WINAPI* SleepConditionVariableCS)(CONDITION_VARIABLE* ConditionVariable,
+                                         CRITICAL_SECTION* CriticalSection,
+                                         DWORD dwMilliseconds);
+
+private:
+  template <typename T>
+  inline bool loadSymbol(HMODULE module, const char* name, T& fn) {
+    FARPROC ptr = GetProcAddress(module, name);
+    if (!ptr)
+      return false;
+
+    fn = reinterpret_cast<T>(ptr);
+    return true;
+  }
+
+  bool supported_;
+};
+
+static ConditionVariableNativeImports sNativeImports;
+
 // Wrapper for native condition variable APIs.
-struct js::ConditionVariable::PlatformData
+struct ConditionVariableNative
 {
+  inline void initialize() {
+    sNativeImports.InitializeConditionVariable(&cv_);
+  }
+
+  inline void destroy() {
+    // Native condition variables don't require cleanup.
+  }
+
+  inline void notify_one() { sNativeImports.WakeConditionVariable(&cv_); }
+
+  inline void notify_all() { sNativeImports.WakeAllConditionVariable(&cv_); }
+
+  inline bool wait(CRITICAL_SECTION* cs, DWORD msec) {
+    return sNativeImports.SleepConditionVariableCS(&cv_, cs, msec);
+  }
+
+private:
   CONDITION_VARIABLE cv_;
 };
 
+// Fallback condition variable support for Windows XP and Server 2003. Given the
+// difficulty of testing on these antiquated platforms and their rapidly
+// diminishing market share, this implementation trades performance for
+// predictable behavior.
+struct ConditionVariableFallback
+{
+  static const uint32_t WAKEUP_MODE_NONE = 0;
+  static const uint32_t WAKEUP_MODE_ONE = 0x40000000;
+  static const uint32_t WAKEUP_MODE_ALL = 0x80000000;
+
+  static const uint32_t WAKEUP_MODE_MASK = WAKEUP_MODE_ONE | WAKEUP_MODE_ALL;
+  static const uint32_t SLEEPERS_COUNT_MASK = ~WAKEUP_MODE_MASK;
+
+  void initialize()
+  {
+    // Initialize the state variable to 0 sleepers, no wakeup.
+    sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
+
+    // Create a semaphore that prevents threads from entering sleep,
+    // or waking other threads while a wakeup is ongoing.
+    sleepWakeupSemaphore_ = CreateSemaphoreW(NULL, 1, 1, NULL);
+    MOZ_RELEASE_ASSERT(sleepWakeupSemaphore_);
+
+    // Use an auto-reset event for waking up a single sleeper.
+    wakeOneEvent_ = CreateEventW(NULL, FALSE, FALSE, NULL);
+    MOZ_RELEASE_ASSERT(wakeOneEvent_);
+
+    // Use a manual-reset event for waking up all sleepers.
+    wakeAllEvent_ = CreateEventW(NULL, TRUE, FALSE, NULL);
+    MOZ_RELEASE_ASSERT(wakeAllEvent_);
+  }
+
+  void destroy()
+  {
+    BOOL r;
+
+    MOZ_RELEASE_ASSERT(sleepersCountAndWakeupMode_ == (0 | WAKEUP_MODE_NONE));
+
+    r = CloseHandle(sleepWakeupSemaphore_);
+    MOZ_RELEASE_ASSERT(r);
+
+    r = CloseHandle(wakeOneEvent_);
+    MOZ_RELEASE_ASSERT(r);
+
+    r = CloseHandle(wakeAllEvent_);
+    MOZ_RELEASE_ASSERT(r);
+  }
+
+private:
+  void wakeup(uint32_t wakeupMode, HANDLE wakeEvent)
+  {
+    // Ensure that only one thread at a time can wake up others.
+    BOOL result = WaitForSingleObject(sleepWakeupSemaphore_, INFINITE);
+    MOZ_RELEASE_ASSERT(result == WAIT_OBJECT_0);
+
+    // Atomically set the wakeup mode and retrieve the number of sleepers.
+    uint32_t wcwm = InterlockedExchangeAdd(&sleepersCountAndWakeupMode_,
+                                           wakeupMode);
+    uint32_t sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
+    MOZ_RELEASE_ASSERT((wcwm & WAKEUP_MODE_MASK) == WAKEUP_MODE_NONE);
+
+    if (sleepersCount > 0) {
+      // If there are any sleepers, set the wake event. The (last) woken
+      // up thread is responsible for releasing the semaphore.
+      BOOL success = SetEvent(wakeEvent);
+      MOZ_RELEASE_ASSERT(success);
+
+    } else {
+      // If there are no sleepers, set the wakeup mode back to 'none'
+      // and release the semaphore ourselves.
+      sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
+
+      BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
+      MOZ_RELEASE_ASSERT(success);
+    }
+  }
+
+public:
+  void notify_one() { wakeup(WAKEUP_MODE_ONE, wakeOneEvent_); }
+
+  void notify_all() { wakeup(WAKEUP_MODE_ALL, wakeAllEvent_); }
+
+  bool wait(CRITICAL_SECTION* userLock, DWORD msec)
+  {
+    // Make sure that we can't enter sleep when there are other threads
+    // that still need to wake up on either of the wake events being set.
+    DWORD result = WaitForSingleObject(sleepWakeupSemaphore_, INFINITE);
+    MOZ_RELEASE_ASSERT(result == WAIT_OBJECT_0);
+
+    // Register ourselves as a sleeper. Use an atomic operation, because
+    // if another thread times out at the same time, it will decrement the
+    // sleepers count without acquiring the semaphore.
+    uint32_t wcwm = InterlockedIncrement(&sleepersCountAndWakeupMode_);
+    MOZ_RELEASE_ASSERT((wcwm & WAKEUP_MODE_MASK) == WAKEUP_MODE_NONE);
+
+    // Now that that this thread has been enlisted as a sleeper, it is safe
+    // again for other threads to do a wakeup.
+    BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
+    MOZ_RELEASE_ASSERT(success);
+
+    // Release the caller's mutex.
+    LeaveCriticalSection(userLock);
+
+    // Wait for either event to become signaled, which happens when
+    // notify_one() or notify_all() is called, or for a timeout.
+    HANDLE handles[2] = { wakeOneEvent_, wakeAllEvent_ };
+    DWORD waitResult = WaitForMultipleObjects(2, handles, FALSE, msec);
+    MOZ_RELEASE_ASSERT(waitResult == WAIT_OBJECT_0 ||
+                       waitResult == WAIT_OBJECT_0 + 1 ||
+                       (waitResult == WAIT_TIMEOUT && msec != INFINITE));
+
+    // Atomically decrease the sleepers count and retrieve the wakeup mode
+    // and new sleepers count.
+    // If the wait returned because wakeOneEvent_ was set, we are certain
+    // that the wakeup mode will be WAKEUP_MODE_ONE. In that case,
+    // atomically reset the wakeup mode to 'none', because if another
+    // thread's sleep times out at same time and it finds that it was the
+    // last sleeper, it decides whether or not to reset the wakeOneEvent_
+    // based on the current wakeup mode.
+    uint32_t sub;
+    if (waitResult == WAIT_OBJECT_0)
+      sub = 1 | WAKEUP_MODE_ONE;
+    else
+      sub = 1;
+    // Note that InterlockedExchangeAdd returns the old value, but it's
+    // easier to work with the new value.
+    wcwm = InterlockedExchangeAdd(&sleepersCountAndWakeupMode_, -sub) - sub;
+
+    uint32_t wakeupMode = wcwm & WAKEUP_MODE_MASK;
+    uint32_t sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
+
+    bool releaseSleepWakeupSemaphore = false;
+
+    if (waitResult == WAIT_OBJECT_0) {
+      // The wake-one event is an auto-reset event so if we're woken by
+      // it, it should already have been reset. We also already removed
+      // the WAKEUP_MODE_ONE bit so the wakeup mode should now be 'none'
+      // again.
+      MOZ_RELEASE_ASSERT(wakeupMode == WAKEUP_MODE_NONE);
+
+      // The signaling thread has acquired the enter-wakeup semaphore and
+      // expects the woken (this) thread to release it again.
+      releaseSleepWakeupSemaphore = true;
+
+    } else if (waitResult == WAIT_TIMEOUT && wakeupMode == WAKEUP_MODE_ONE &&
+               sleepersCount == 0) {
+      // In theory a race condition is possible where the last sleeper
+      // times out right at the moment that another thread signals it.
+      // If that just happened we now have a dangling signal event and
+      // mode, but no threads to be woken up by it, and we need to clean
+      // that up.
+      BOOL success = ResetEvent(wakeOneEvent_);
+      MOZ_RELEASE_ASSERT(success);
+
+      // This is safe - we are certain there are no other sleepers that
+      // could wake up right now, and the semaphore ensures that no
+      // non-sleeping threads are messing with
+      // sleepersCountAndWakeupMode_.
+      sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
+
+      // The signaling thread has acquired the sleep-wakeup semaphore and
+      // expects the woken thread to release it. But since there are no
+      // sleeping threads left this thread will do it instead.
+      releaseSleepWakeupSemaphore = true;
+
+    } else if (wakeupMode == WAKEUP_MODE_ALL && sleepersCount == 0) {
+      // If this was the last thread waking up in response to a
+      // notify_all, clear the wakeup mode and reset the wake-all event.
+      // A race condition similar to the case described above could
+      // occur, so waitResult could be WAIT_TIMEOUT, but that doesn't
+      // matter for the actions that need to be taken.
+      MOZ_RELEASE_ASSERT(waitResult = WAIT_OBJECT_0 + 1 ||
+                         waitResult == WAIT_TIMEOUT);
+
+      BOOL success = ResetEvent(wakeAllEvent_);
+      MOZ_RELEASE_ASSERT(success);
+
+      sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
+
+      // The broadcasting thread has acquired the enter-wakeup semaphore
+      // and expects the last thread that wakes up to release it.
+      releaseSleepWakeupSemaphore = true;
+
+    } else if ((waitResult == WAIT_TIMEOUT && msec != INFINITE) ||
+               (waitResult == WAIT_OBJECT_0 + 1 &&
+                wakeupMode == WAKEUP_MODE_ALL)) {
+      // Either:
+      //   * The wait timed out but found no active notify_one or notify_all
+      //     the moment it decreased the wait count.
+      //   * A notify_all woke up this thread but there are more threads
+      //     that need to be woken up by the wake-all event.
+      // These are ordinary conditions in which we don't have to do
+      // anything.
+
+    } else {
+      MOZ_CRASH("invalid wakeup condition");
+    }
+
+    // Release the enter-wakeup semaphore if the wakeup condition requires
+    // us to do it.
+    if (releaseSleepWakeupSemaphore) {
+      BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
+      MOZ_RELEASE_ASSERT(success);
+    }
+
+    // Reacquire the user mutex.
+    EnterCriticalSection(userLock);
+
+    // Return true if woken up, false when timed out.
+    if (waitResult == WAIT_TIMEOUT) {
+      SetLastError(ERROR_TIMEOUT);
+      return false;
+    }
+    return true;
+  }
+
+private:
+  uint32_t sleepersCountAndWakeupMode_;
+  HANDLE sleepWakeupSemaphore_;
+  HANDLE wakeOneEvent_;
+  HANDLE wakeAllEvent_;
+};
+
+struct js::ConditionVariable::PlatformData
+{
+  union
+  {
+    ConditionVariableNative native;
+    ConditionVariableFallback fallback;
+  };
+};
+
 js::ConditionVariable::ConditionVariable()
 {
-  InitializeConditionVariable(&platformData()->cv_);
+  if (sNativeImports.supported())
+    platformData()->native.initialize();
+  else
+    platformData()->fallback.initialize();
 }
 
 void
 js::ConditionVariable::notify_one()
 {
-  WakeConditionVariable(&platformData()->cv_);
+  if (sNativeImports.supported())
+    platformData()->native.notify_one();
+  else
+    platformData()->fallback.notify_one();
 }
 
 void
 js::ConditionVariable::notify_all()
 {
-  WakeAllConditionVariable(&platformData()->cv_);
+  if (sNativeImports.supported())
+    platformData()->native.notify_all();
+  else
+    platformData()->fallback.notify_all();
 }
 
 void
 js::ConditionVariable::wait(UniqueLock<Mutex>& lock)
 {
   CRITICAL_SECTION* cs = &lock.lock.platformData()->criticalSection;
-  bool r = SleepConditionVariableCS(&platformData()->cv_, cs, INFINITE);
+  bool r;
+  if (sNativeImports.supported())
+    r = platformData()->native.wait(cs, INFINITE);
+  else
+    r = platformData()->fallback.wait(cs, INFINITE);
   MOZ_RELEASE_ASSERT(r);
 }
 
@@ -82,7 +390,11 @@ js::ConditionVariable::wait_for(UniqueLock<Mutex>& lock,
                  ? INFINITE
                  : static_cast<DWORD>(msecd);
 
-  BOOL r = SleepConditionVariableCS(&platformData()->cv_, cs, msec);
+  BOOL r;
+  if (sNativeImports.supported())
+    r = platformData()->native.wait(cs, msec);
+  else
+    r = platformData()->fallback.wait(cs, msec);
   if (r)
     return CVStatus::NoTimeout;
   MOZ_RELEASE_ASSERT(GetLastError() == ERROR_TIMEOUT);
@@ -91,7 +403,10 @@ js::ConditionVariable::wait_for(UniqueLock<Mutex>& lock,
 
 js::ConditionVariable::~ConditionVariable()
 {
-  // Native condition variables don't require cleanup.
+  if (sNativeImports.supported())
+    platformData()->native.destroy();
+  else
+    platformData()->fallback.destroy();
 }
 
 inline js::ConditionVariable::PlatformData*
diff --git a/js/src/vm/Stopwatch.h b/js/src/vm/Stopwatch.h
index 38a3eb801..a1b8bbbcb 100644
--- a/js/src/vm/Stopwatch.h
+++ b/js/src/vm/Stopwatch.h
@@ -301,9 +301,9 @@ struct PerformanceMonitoring {
 
 #if WINVER >= 0x0600
 struct cpuid_t {
-    uint16_t group_;
-    uint8_t number_;
-    cpuid_t(uint16_t group, uint8_t number)
+    WORD group_;
+    BYTE number_;
+    cpuid_t(WORD group, BYTE number)
         : group_(group),
           number_(number)
     { }
diff --git a/js/xpconnect/shell/xpcshell.exe.manifest b/js/xpconnect/shell/xpcshell.exe.manifest
index c35b77af4..db2aa0861 100644
--- a/js/xpconnect/shell/xpcshell.exe.manifest
+++ b/js/xpconnect/shell/xpcshell.exe.manifest
@@ -25,6 +25,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/mfbt/ThreadLocal.h b/mfbt/ThreadLocal.h
index 391e748ad..880e67735 100644
--- a/mfbt/ThreadLocal.h
+++ b/mfbt/ThreadLocal.h
@@ -9,7 +9,20 @@
 #ifndef mozilla_ThreadLocal_h
 #define mozilla_ThreadLocal_h
 
-#if !defined(XP_WIN)
+#if defined(XP_WIN)
+// This file will get included in any file that wants to add a profiler mark.
+// In order to not bring <windows.h> together we could include windef.h and
+// winbase.h which are sufficient to get the prototypes for the Tls* functions.
+// # include <windef.h>
+// # include <winbase.h>
+// Unfortunately, even including these headers causes us to add a bunch of ugly
+// stuff to our namespace e.g #define CreateEvent CreateEventW
+extern "C" {
+__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long);
+__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void*);
+__declspec(dllimport) unsigned long __stdcall TlsAlloc();
+}
+#else
 #  include <pthread.h>
 #  include <signal.h>
 #endif
@@ -31,7 +44,7 @@ typedef sig_atomic_t sig_safe_t;
 
 namespace detail {
 
-#if defined(HAVE_THREAD_TLS_KEYWORD) || defined(XP_WIN) || defined(XP_MACOSX)
+#if defined(HAVE_THREAD_TLS_KEYWORD)
 #define MOZ_HAS_THREAD_LOCAL
 #endif
 
@@ -78,7 +91,11 @@ template<typename T>
 class ThreadLocal
 {
 #ifndef MOZ_HAS_THREAD_LOCAL
+#if defined(XP_WIN)
+  typedef unsigned long key_t;
+#else
   typedef pthread_key_t key_t;
+#endif
 
   // Integral types narrower than void* must be extended to avoid
   // warnings from valgrind on some platforms.  This helper type
@@ -144,7 +161,12 @@ ThreadLocal<T>::init()
   return true;
 #else
   if (!initialized()) {
+#ifdef XP_WIN
+    mKey = TlsAlloc();
+    mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
+#else
     mInited = !pthread_key_create(&mKey, nullptr);
+#endif
   }
   return mInited;
 #endif
@@ -159,7 +181,11 @@ ThreadLocal<T>::get() const
 #else
   MOZ_ASSERT(initialized());
   void* h;
+#ifdef XP_WIN
+  h = TlsGetValue(mKey);
+#else
   h = pthread_getspecific(mKey);
+#endif
   return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
 #endif
 }
@@ -173,7 +199,11 @@ ThreadLocal<T>::set(const T aValue)
 #else
   MOZ_ASSERT(initialized());
   void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
+#ifdef XP_WIN
+  bool succeeded = TlsSetValue(mKey, h);
+#else
   bool succeeded = !pthread_setspecific(mKey, h);
+#endif
   if (!succeeded) {
     MOZ_CRASH();
   }
@@ -181,11 +211,7 @@ ThreadLocal<T>::set(const T aValue)
 }
 
 #ifdef MOZ_HAS_THREAD_LOCAL
-#if defined(XP_WIN) || defined(XP_MACOSX)
-#define MOZ_THREAD_LOCAL(TYPE) thread_local mozilla::detail::ThreadLocal<TYPE>
-#else
 #define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
-#endif
 #else
 #define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
 #endif
diff --git a/mfbt/WindowsVersion.h b/mfbt/WindowsVersion.h
index 4d0cb374b..f8b071861 100644
--- a/mfbt/WindowsVersion.h
+++ b/mfbt/WindowsVersion.h
@@ -84,11 +84,44 @@ IsWindowsBuildOrLater(uint32_t aBuild)
   return false;
 }
 
-// Although many of the older versions are not supported, we should keep
-// these entries for completeness (since they don't take any resources of
-// note), and to cater to corner cases for applications running e.g. in
-// Windows' compatibility mode.
+#if defined(_M_X64) || defined(_M_AMD64)
+// We support only Win7 or later on Win64.
+MOZ_ALWAYS_INLINE bool
+IsXPSP3OrLater()
+{
+  return true;
+}
+
+MOZ_ALWAYS_INLINE bool
+IsWin2003OrLater()
+{
+  return true;
+}
+
+MOZ_ALWAYS_INLINE bool
+IsWin2003SP2OrLater()
+{
+  return true;
+}
+
+MOZ_ALWAYS_INLINE bool
+IsVistaOrLater()
+{
+  return true;
+}
+
+MOZ_ALWAYS_INLINE bool
+IsVistaSP1OrLater()
+{
+  return true;
+}
 
+MOZ_ALWAYS_INLINE bool
+IsWin7OrLater()
+{
+  return true;
+}
+#else
 MOZ_ALWAYS_INLINE bool
 IsXPSP3OrLater()
 {
@@ -124,6 +157,7 @@ IsWin7OrLater()
 {
   return IsWindowsVersionOrLater(0x06010000ul);
 }
+#endif
 
 MOZ_ALWAYS_INLINE bool
 IsWin7SP1OrLater()
@@ -156,6 +190,41 @@ IsNotWin7PreRTM()
          IsWindowsBuildOrLater(7600);
 }
 
+MOZ_ALWAYS_INLINE bool
+IsWin7AndPre2000Compatible() {
+  /*
+   * See Bug 1279171.
+   * We'd like to avoid using WMF on specific OS version when compatibility
+   * mode is in effect. The purpose of this function is to check if FF runs on
+   * Win7 OS with application compatibility mode being set to 95/98/ME.
+   * Those compatibility mode options (95/98/ME) can only display and
+   * be selected for 32-bit application.
+   * If the compatibility mode is in effect, the GetVersionEx function will
+   * report the OS as it identifies itself, which may not be the OS that is
+   * installed.
+   * Note : 1) We only target for Win7 build number greater than 7600.
+   *        2) GetVersionEx may be altered or unavailable for release after
+   *           Win8.1. Set pragma to avoid build warning as error.
+   */
+  bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
+  if (!isWin7) {
+    return false;
+  }
+
+  OSVERSIONINFOEX info;
+  ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
+
+  info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#pragma warning(push)
+#pragma warning(disable:4996)
+  bool success = GetVersionEx((LPOSVERSIONINFO) &info);
+#pragma warning(pop)
+  if (!success) {
+    return false;
+  }
+  return info.dwMajorVersion < 5;
+}
+
 } // namespace mozilla
 
 #endif /* mozilla_WindowsVersion_h */
diff --git a/mozglue/build/WindowsDllBlocklist.cpp b/mozglue/build/WindowsDllBlocklist.cpp
index 9b63d6673..a3c662723 100644
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -67,6 +67,7 @@ struct DllBlockInfo {
   enum {
     FLAGS_DEFAULT = 0,
     BLOCK_WIN8PLUS_ONLY = 1,
+    BLOCK_XP_ONLY = 2,
     USE_TIMESTAMP = 4,
   } flags;
 };
@@ -155,6 +156,9 @@ static DllBlockInfo sWindowsDllBlocklist[] = {
   // Topcrash with Conduit SearchProtect, bug 944542
   { "spvc32.dll", ALL_VERSIONS },
 
+  // XP topcrash with F-Secure, bug 970362
+  { "fs_ccf_ni_umh32.dll", MAKE_VERSION(1, 42, 101, 0), DllBlockInfo::BLOCK_XP_ONLY },
+
   // Topcrash with V-bates, bug 1002748 and bug 1023239
   { "libinject.dll", UNVERSIONED },
   { "libinject2.dll", 0x537DDC93, DllBlockInfo::USE_TIMESTAMP },
@@ -672,6 +676,11 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
       goto continue_loading;
     }
 
+    if ((info->flags == DllBlockInfo::BLOCK_XP_ONLY) &&
+        IsWin2003OrLater()) {
+      goto continue_loading;
+    }
+
     unsigned long long fVersion = ALL_VERSIONS;
 
     if (info->maxVersion != ALL_VERSIONS) {
@@ -740,7 +749,7 @@ continue_loading:
       return STATUS_DLL_NOT_FOUND;
     }
 
-    if (!CheckASLR(full_fname.get())) {
+    if (IsVistaOrLater() && !CheckASLR(full_fname.get())) {
       printf_stderr("LdrLoadDll: Blocking load of '%s'.  XPCOM components must support ASLR.\n", dllName);
       return STATUS_DLL_NOT_FOUND;
     }
diff --git a/mozglue/misc/TimeStamp_windows.cpp b/mozglue/misc/TimeStamp_windows.cpp
index 683c2209a..cd519affd 100644
--- a/mozglue/misc/TimeStamp_windows.cpp
+++ b/mozglue/misc/TimeStamp_windows.cpp
@@ -5,7 +5,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Implement TimeStamp::Now() with QueryPerformanceCounter() controlled with
-// values of GetTickCount64().
+// values of GetTickCount().
 
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/TimeStamp.h"
@@ -69,7 +69,7 @@ static const DWORD kDefaultTimeIncrement = 156001;
  * further just referred as [mt], meaning milli-ticks.
  *
  * This is needed to preserve maximum precision of the performance frequency
- * representation.  GetTickCount64 values in milliseconds are multiplied with
+ * representation.  GetTickCount values in milliseconds are multiplied with
  * frequency per second.  Therefor we need to multiply QPC value by 1000 to
  * have the same units to allow simple arithmentic with both QPC and GTC.
  */
@@ -156,8 +156,41 @@ static CRITICAL_SECTION sTimeStampLock;
 // Kept in [mt]
 static ULONGLONG sFaultIntoleranceCheckpoint = 0;
 
+// Used only when GetTickCount64 is not available on the platform.
+// Last result of GetTickCount call.
+//
+// Kept in [ms]
+static DWORD sLastGTCResult = 0;
+
+// Higher part of the 64-bit value of MozGetTickCount64,
+// incremented atomically.
+static DWORD sLastGTCRollover = 0;
+
 namespace mozilla {
 
+typedef ULONGLONG (WINAPI* GetTickCount64_t)();
+static GetTickCount64_t sGetTickCount64 = nullptr;
+
+// Function protecting GetTickCount result from rolling over,
+// result is in [ms]
+static ULONGLONG WINAPI
+MozGetTickCount64()
+{
+  DWORD GTC = ::GetTickCount();
+
+  // Cheaper then CMPXCHG8B
+  AutoCriticalSection lock(&sTimeStampLock);
+
+  // Pull the rollover counter forward only if new value of GTC goes way
+  // down under the last saved result
+  if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30))) {
+    ++sLastGTCRollover;
+  }
+
+  sLastGTCResult = GTC;
+  return ULONGLONG(sLastGTCRollover) << 32 | sLastGTCResult;
+}
+
 // Result is in [mt]
 static inline ULONGLONG
 PerformanceCounter()
@@ -322,7 +355,7 @@ TimeStampValue::CheckQPC(const TimeStampValue& aOther) const
   if (duration < sHardFailureLimit) {
     // Interval between the two time stamps is very short, consider
     // QPC as unstable and record a failure.
-    uint64_t now = ms2mt(GetTickCount64());
+    uint64_t now = ms2mt(sGetTickCount64());
 
     AutoCriticalSection lock(&sTimeStampLock);
 
@@ -452,6 +485,17 @@ TimeStamp::Startup()
 
   gInitialized = true;
 
+  // Decide which implementation to use for the high-performance timer.
+
+  HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
+  sGetTickCount64 = reinterpret_cast<GetTickCount64_t>(
+    GetProcAddress(kernelDLL, "GetTickCount64"));
+  if (!sGetTickCount64) {
+    // If the platform does not support the GetTickCount64 (Windows XP doesn't),
+    // then use our fallback implementation based on GetTickCount.
+    sGetTickCount64 = MozGetTickCount64;
+  }
+
   InitializeCriticalSectionAndSpinCount(&sTimeStampLock, kLockSpinCount);
 
   sHasStableTSC = HasStableTSC();
@@ -460,10 +504,10 @@ TimeStamp::Startup()
   LARGE_INTEGER freq;
   sUseQPC = ::QueryPerformanceFrequency(&freq);
   if (!sUseQPC) {
-    // No Performance Counter.  Fall back to use GetTickCount64.
+    // No Performance Counter.  Fall back to use GetTickCount.
     InitResolution();
 
-    LOG(("TimeStamp: using GetTickCount64"));
+    LOG(("TimeStamp: using GetTickCount"));
     return;
   }
 
@@ -490,7 +534,7 @@ TimeStamp::Now(bool aHighResolution)
 
   // Both values are in [mt] units.
   ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
-  ULONGLONG GTC = ms2mt(GetTickCount64());
+  ULONGLONG GTC = ms2mt(sGetTickCount64());
   return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
 }
 
diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp
index 184757d33..1bfd1fc91 100644
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -40,6 +40,7 @@
 #include "xpcpublic.h"
 
 #if defined(XP_WIN)
+#include "mozilla/WindowsVersion.h"
 #include "ShutdownLayer.h"
 #endif
 
@@ -1723,6 +1724,21 @@ nsSocketTransport::OnSocketConnected()
         NS_ASSERTION(mFDref == 1, "wrong socket ref count");
         SetSocketName(mFD);
         mFDconnected = true;
+
+#ifdef XP_WIN
+        if (!IsWin2003OrLater()) { // windows xp
+            PRSocketOptionData opt;
+            opt.option = PR_SockOpt_RecvBufferSize;
+            if (PR_GetSocketOption(mFD, &opt) == PR_SUCCESS) {
+                SOCKET_LOG(("%p checking rwin on xp originally=%u\n",
+                            this, opt.value.recv_buffer_size));
+                if (opt.value.recv_buffer_size < 65535) {
+                    opt.value.recv_buffer_size = 65535;
+                    PR_SetSocketOption(mFD, &opt);
+                }
+            }
+        }
+#endif
     }
 
     // Ensure keepalive is configured correctly if previously enabled.
diff --git a/netwerk/base/nsSocketTransportService2.cpp b/netwerk/base/nsSocketTransportService2.cpp
index 068bf0eca..d2f20651e 100644
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -28,6 +28,10 @@
 #include "nsIWidget.h"
 #include "mozilla/dom/FlyWebService.h"
 
+#if defined(XP_WIN)
+#include "mozilla/WindowsVersion.h"
+#endif
+
 namespace mozilla {
 namespace net {
 
@@ -1200,7 +1204,12 @@ nsSocketTransportService::UpdateSendBufferPref(nsIPrefBranch *pref)
     }
 
 #if defined(XP_WIN)
-    mSendBufferSize = 131072 * 4;
+    // If the pref is not set but this is windows set it depending on windows version
+    if (!IsWin2003OrLater()) { // windows xp
+        mSendBufferSize = 131072;
+    } else { // vista or later
+        mSendBufferSize = 131072 * 4;
+    }
 #endif
 }
 
diff --git a/netwerk/test/TestUDPSocket.cpp b/netwerk/test/TestUDPSocket.cpp
index 0ec43a650..9236d2ea3 100644
--- a/netwerk/test/TestUDPSocket.cpp
+++ b/netwerk/test/TestUDPSocket.cpp
@@ -13,6 +13,9 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsITimer.h"
 #include "mozilla/net/DNS.h"
+#ifdef XP_WIN
+#include "mozilla/WindowsVersion.h"
+#endif
 #include "prerror.h"
 
 #define REQUEST  0x68656c6f
@@ -331,6 +334,16 @@ main(int32_t argc, char *argv[])
   }
   RefPtr<MulticastTimerCallback> timerCb = new MulticastTimerCallback();
 
+  // The following multicast tests using multiple sockets require a firewall
+  // exception on Windows XP (the earliest version of Windows we now support)
+  // before they pass. For now, we'll skip them here. Later versions of Windows
+  // (Win2003 and onward) don't seem to have this issue.
+#ifdef XP_WIN
+  if (!mozilla::IsWin2003OrLater()) {   // i.e. if it is WinXP
+    goto close;
+  }
+#endif
+
   // Join multicast group
   printf("Joining multicast group\n");
   phase = TEST_MULTICAST;
diff --git a/netwerk/wifi/moz.build b/netwerk/wifi/moz.build
index e3edb0842..b6ddd2139 100644
--- a/netwerk/wifi/moz.build
+++ b/netwerk/wifi/moz.build
@@ -45,6 +45,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
         'nsWifiScannerWin.cpp',
         'win_wifiScanner.cpp',
         'win_wlanLibrary.cpp',
+        'win_xp_wifiScanner.cpp'
     ]
 elif CONFIG['OS_ARCH'] == 'SunOS':
     CXXFLAGS += CONFIG['GLIB_CFLAGS']
diff --git a/netwerk/wifi/nsWifiMonitor.h b/netwerk/wifi/nsWifiMonitor.h
index 665798efc..3783d38bd 100644
--- a/netwerk/wifi/nsWifiMonitor.h
+++ b/netwerk/wifi/nsWifiMonitor.h
@@ -76,7 +76,7 @@ class nsWifiMonitor final : nsIRunnable, nsIWifiMonitor, nsIObserver
   mozilla::ReentrantMonitor mReentrantMonitor;
 
 #ifdef XP_WIN
-  nsAutoPtr<WinWifiScanner> mWinWifiScanner;
+  nsAutoPtr<WindowsWifiScannerInterface> mWinWifiScanner;
 #endif
 };
 #else
diff --git a/netwerk/wifi/nsWifiScannerWin.cpp b/netwerk/wifi/nsWifiScannerWin.cpp
index 6089c45c6..ef18706e4 100644
--- a/netwerk/wifi/nsWifiScannerWin.cpp
+++ b/netwerk/wifi/nsWifiScannerWin.cpp
@@ -12,6 +12,8 @@
 #include "nsServiceManagerUtils.h"
 #include "nsWifiAccessPoint.h"
 #include "win_wifiScanner.h"
+#include "win_xp_wifiScanner.h"
+#include "mozilla/WindowsVersion.h"
 
 using namespace mozilla;
 
@@ -29,7 +31,14 @@ nsresult
 nsWifiMonitor::DoScan()
 {
     if (!mWinWifiScanner) {
-      mWinWifiScanner = new WinWifiScanner();
+      if (IsWin2003OrLater()) {
+        mWinWifiScanner = new WinWifiScanner();
+        LOG(("Using Windows 2003+ wifi scanner."));
+      } else {
+        mWinWifiScanner = new WinXPWifiScanner();
+        LOG(("Using Windows XP wifi scanner."));
+      }
+
       if (!mWinWifiScanner) {
         // TODO: Probably return OOM error
         return NS_ERROR_FAILURE;
diff --git a/netwerk/wifi/win_wifiScanner.h b/netwerk/wifi/win_wifiScanner.h
index 79b1bf132..b43c23899 100644
--- a/netwerk/wifi/win_wifiScanner.h
+++ b/netwerk/wifi/win_wifiScanner.h
@@ -11,10 +11,19 @@
 
 class nsWifiAccessPoint;
 
-class WinWifiScanner final {
+// This class allows the wifi monitor to use WinWifiScanner and WinXPWifiScanner interchangeably.
+class WindowsWifiScannerInterface {
+public:
+  virtual ~WindowsWifiScannerInterface() {}
+
+  virtual nsresult GetAccessPointsFromWLAN(nsCOMArray<nsWifiAccessPoint> &accessPoints) = 0;
+};
+
+
+class WinWifiScanner : public WindowsWifiScannerInterface {
  public:
   WinWifiScanner();
-  ~WinWifiScanner();
+  virtual ~WinWifiScanner();
 
   /**
    * GetAccessPointsFromWLAN
diff --git a/old-configure.in b/old-configure.in
index 92a5f729e..3024c2d01 100644
--- a/old-configure.in
+++ b/old-configure.in
@@ -212,7 +212,7 @@ dnl ========================================================
 dnl Special win32 checks
 dnl ========================================================
 
-WINVER=601
+WINVER=502
 
 case "$target" in
 *-mingw*)
@@ -1013,7 +1013,12 @@ case "$target" in
         IMPORT_LIB_SUFFIX=lib
         MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        WIN32_SUBSYSTEM_VERSION=6.01
+        dnl Set subsystem version 5 for Windows XP.
+        if test "$CPU_ARCH" = "x86"; then
+            WIN32_SUBSYSTEM_VERSION=5.01
+        else
+            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
@@ -3312,6 +3317,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
@@ -3330,6 +3338,11 @@ x86_64)
   ;;
 esac
 
+MOZ_ARG_ENABLE_BOOL(require-all-d3dc-versions,
+[  --enable-require-all-d3dc-versions Require all versions of the D3D compiler needed for supported Windows systems.],
+    MOZ_REQUIRE_ALL_D3DCS=1,
+    MOZ_REQUIRE_ALL_D3DCS=)
+
 # This is potentially set in external mozconfig files; if it's set,
 # then the build exposes the "webgl" context name, which is reserved
 # for conformant implementations.
@@ -3387,19 +3400,89 @@ 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.
+
+  if test "$HAVE_64BIT_BUILD"; then
+    AC_MSG_RESULT([We are building a 64-bit binary, skip checking d3dcompiler_43.])
+  else
+    # 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
+  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
 
@@ -5268,6 +5351,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/toolkit/components/alerts/nsAlertsService.cpp b/toolkit/components/alerts/nsAlertsService.cpp
index dd67ad983..35418dd17 100644
--- a/toolkit/components/alerts/nsAlertsService.cpp
+++ b/toolkit/components/alerts/nsAlertsService.cpp
@@ -22,10 +22,6 @@
 #include "nsIFaviconService.h"
 #endif // MOZ_PLACES
 
-#ifdef XP_WIN
-#include <shellapi.h>
-#endif
-
 using namespace mozilla;
 
 using mozilla::dom::ContentChild;
@@ -158,12 +154,23 @@ bool nsAlertsService::ShouldShowAlert()
   bool result = true;
 
 #ifdef XP_WIN
-  QUERY_USER_NOTIFICATION_STATE qstate;
-  if (SUCCEEDED(SHQueryUserNotificationState(&qstate))) {
-    if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) {
-       result = false;
+  HMODULE shellDLL = ::LoadLibraryW(L"shell32.dll");
+  if (!shellDLL)
+    return result;
+
+  SHQueryUserNotificationStatePtr pSHQueryUserNotificationState =
+    (SHQueryUserNotificationStatePtr) ::GetProcAddress(shellDLL, "SHQueryUserNotificationState");
+
+  if (pSHQueryUserNotificationState) {
+    MOZ_QUERY_USER_NOTIFICATION_STATE qstate;
+    if (SUCCEEDED(pSHQueryUserNotificationState(&qstate))) {
+      if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) {
+         result = false;
+      }
     }
   }
+
+  ::FreeLibrary(shellDLL);
 #endif
 
   return result;
diff --git a/toolkit/components/alerts/nsAlertsService.h b/toolkit/components/alerts/nsAlertsService.h
index d2b2e1e6c..3f23eaabf 100644
--- a/toolkit/components/alerts/nsAlertsService.h
+++ b/toolkit/components/alerts/nsAlertsService.h
@@ -10,6 +10,23 @@
 #include "nsCOMPtr.h"
 #include "nsXULAlerts.h"
 
+#ifdef XP_WIN
+typedef enum tagMOZ_QUERY_USER_NOTIFICATION_STATE {
+    QUNS_NOT_PRESENT = 1,
+    QUNS_BUSY = 2,
+    QUNS_RUNNING_D3D_FULL_SCREEN = 3,
+    QUNS_PRESENTATION_MODE = 4,
+    QUNS_ACCEPTS_NOTIFICATIONS = 5,
+    QUNS_QUIET_TIME = 6,
+    QUNS_IMMERSIVE = 7
+} MOZ_QUERY_USER_NOTIFICATION_STATE;
+
+extern "C" {
+// This function is Windows Vista or later
+typedef HRESULT (__stdcall *SHQueryUserNotificationStatePtr)(MOZ_QUERY_USER_NOTIFICATION_STATE *pquns);
+}
+#endif // defined(XP_WIN)
+
 class nsAlertsService : public nsIAlertsService,
                         public nsIAlertsDoNotDisturb
 {
diff --git a/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest b/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest
index e6bfba8ca..cb317c47d 100644
--- a/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest
+++ b/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest
@@ -20,6 +20,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/toolkit/crashreporter/client/crashreporter.exe.manifest b/toolkit/crashreporter/client/crashreporter.exe.manifest
index e6b2ceefb..f8587bfad 100644
--- a/toolkit/crashreporter/client/crashreporter.exe.manifest
+++ b/toolkit/crashreporter/client/crashreporter.exe.manifest
@@ -32,6 +32,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/toolkit/library/libxul.mk b/toolkit/library/libxul.mk
index 9e7e8beee..d918d9c84 100644
--- a/toolkit/library/libxul.mk
+++ b/toolkit/library/libxul.mk
@@ -16,6 +16,16 @@ EXTRA_DEPS += symverscript
 endif
 endif
 
+ifdef MOZ_WEBRTC
+ifeq (WINNT,$(OS_TARGET))
+ifndef MOZ_HAS_WINSDK_WITH_D3D
+OS_LDFLAGS += \
+  -LIBPATH:'$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_D3D_CPU_SUFFIX)' \
+  $(NULL)
+endif
+endif
+endif
+
 # Generate GDB pretty printer-autoload files only on Linux. OSX's GDB is
 # too old to support Python pretty-printers; if this changes, we could make
 # this 'ifdef GNU_CC'.
diff --git a/toolkit/mozapps/update/updater/updater.exe.comctl32.manifest b/toolkit/mozapps/update/updater/updater.exe.comctl32.manifest
index 6bb850199..9a6cdb565 100644
--- a/toolkit/mozapps/update/updater/updater.exe.comctl32.manifest
+++ b/toolkit/mozapps/update/updater/updater.exe.comctl32.manifest
@@ -32,6 +32,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/toolkit/mozapps/update/updater/updater.exe.manifest b/toolkit/mozapps/update/updater/updater.exe.manifest
index 619b4abfe..cd229c954 100644
--- a/toolkit/mozapps/update/updater/updater.exe.manifest
+++ b/toolkit/mozapps/update/updater/updater.exe.manifest
@@ -20,6 +20,7 @@
       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
     </application>
   </compatibility>
 </assembly>
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 4a1d3046f..4979e1652 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -98,6 +98,7 @@
 #include <intrin.h>
 #include <math.h>
 #include "cairo/cairo-features.h"
+#include "mozilla/WindowsVersion.h"
 #include "mozilla/mscom/MainThreadRuntime.h"
 #include "mozilla/widget/AudioSession.h"
 
@@ -3105,7 +3106,10 @@ XREMain::XRE_mainInit(bool* aExitFlag)
     // manual font file I/O on _all_ system fonts.  To avoid this, load the
     // dwrite library and create a factory as early as possible so that the
     // FntCache service is ready by the time it's needed.
-    CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
+
+    if (IsVistaOrLater()) {
+      CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
+    }
   }
 #endif
 
@@ -4831,7 +4835,7 @@ enum {
   kE10sDisabledForAddons = 7,
   kE10sForceDisabled = 8,
   // kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
-  // kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
+  kE10sDisabledForOperatingSystem = 10,
 };
 
 const char* kAccessibilityLastRunDatePref = "accessibility.lastLoadDate";
@@ -4908,6 +4912,19 @@ MultiprocessBlockPolicy() {
   }
 #endif
 
+  /**
+   * Avoids enabling e10s for Windows XP users on the release channel.
+   */
+#if defined(XP_WIN)
+  if (!IsVistaOrLater()) {
+    nsAdoptingCString channelName = Preferences::GetDefaultCString("app.update.channel");
+    if (channelName.EqualsLiteral("release") || channelName.EqualsLiteral("esr")) {
+      gMultiprocessBlockPolicy = kE10sDisabledForOperatingSystem;
+      return gMultiprocessBlockPolicy;
+    }
+  }
+#endif // XP_WIN
+
   /*
    * None of the blocking policies matched, so e10s is allowed to run.
    * Cache the information and return 0, indicating success.
diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp
index 1e67ea7ce..0e85532b9 100644
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -24,7 +24,6 @@
 
 #ifdef XP_WIN
 #include <process.h>
-#include <shobjidl.h>
 #include "mozilla/ipc/WindowsMessageLoop.h"
 #endif
 
@@ -120,6 +119,10 @@ using mozilla::startup::sChildProcessType;
 
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
+#ifdef XP_WIN
+static const wchar_t kShellLibraryName[] =  L"shell32.dll";
+#endif
+
 nsresult
 XRE_LockProfileDirectory(nsIFile* aDirectory,
                          nsISupports* *aLockObject)
@@ -267,9 +270,26 @@ XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
 void
 SetTaskbarGroupId(const nsString& aId)
 {
-    if (FAILED(SetCurrentProcessExplicitAppUserModelID(aId.get()))) {
+    typedef HRESULT (WINAPI * SetCurrentProcessExplicitAppUserModelIDPtr)(PCWSTR AppID);
+
+    SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nullptr;
+
+    HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
+
+    funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
+                          GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
+
+    if (!funcAppUserModelID) {
+        ::FreeLibrary(hDLL);
+        return;
+    }
+
+    if (FAILED(funcAppUserModelID(aId.get()))) {
         NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
     }
+
+    if (hDLL)
+        ::FreeLibrary(hDLL);
 }
 #endif
 
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index 09168319f..2fbd324b7 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -48,6 +48,7 @@
 #ifdef XP_WIN
 #include <windows.h>
 #include <shlobj.h>
+#include "mozilla/WindowsVersion.h"
 #endif
 #ifdef XP_MACOSX
 #include "nsILocalFileMac.h"
@@ -761,12 +762,15 @@ nsXREDirProvider::LoadContentProcessTempDir()
 static bool
 IsContentSandboxDisabled()
 {
-  bool isSandboxDisabled = false;
   if (!BrowserTabsRemoteAutostart()) {
     return false;
   }
-#if defined(XP_WIN) || defined(XP_MACOSX)
-  isSandboxDisabled = Preferences::GetInt("security.sandbox.content.level") < 1;
+#if defined(XP_WIN)
+  const bool isSandboxDisabled = !mozilla::IsVistaOrLater() ||
+    (Preferences::GetInt("security.sandbox.content.level") < 1);
+#elif defined(XP_MACOSX)
+  const bool isSandboxDisabled =
+    Preferences::GetInt("security.sandbox.content.level") < 1;
 #endif
   return isSandboxDisabled;
 }
diff --git a/toolkit/xre/test/win/TestDllInterceptor.cpp b/toolkit/xre/test/win/TestDllInterceptor.cpp
index 57d68ea77..dff71817f 100644
--- a/toolkit/xre/test/win/TestDllInterceptor.cpp
+++ b/toolkit/xre/test/win/TestDllInterceptor.cpp
@@ -2,6 +2,11 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#if _WIN32_WINNT < 0x0600
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
 #include <shlobj.h>
 #include <stdio.h>
 
diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp
index 5c8693957..e53db69c5 100644
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -245,7 +245,13 @@ RemovePrefForDriverVersion()
 static OperatingSystem
 BlacklistOSToOperatingSystem(const nsAString& os)
 {
-  if (os.EqualsLiteral("WINNT 6.1"))
+  if (os.EqualsLiteral("WINNT 5.1"))
+    return OperatingSystem::WindowsXP;
+  else if (os.EqualsLiteral("WINNT 5.2"))
+    return OperatingSystem::WindowsServer2003;
+  else if (os.EqualsLiteral("WINNT 6.0"))
+    return OperatingSystem::WindowsVista;
+  else if (os.EqualsLiteral("WINNT 6.1"))
     return OperatingSystem::Windows7;
   else if (os.EqualsLiteral("WINNT 6.2"))
     return OperatingSystem::Windows8;
diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h
index 443852330..e2502c559 100644
--- a/widget/LookAndFeel.h
+++ b/widget/LookAndFeel.h
@@ -440,7 +440,6 @@ public:
    * Operating system versions.
    */
   enum OperatingSystemVersion {
-    // XXX: The XP and Vista values can now be removed (see bug 1330146).
     eOperatingSystemVersion_WindowsXP = 0,
     eOperatingSystemVersion_WindowsVista,
     eOperatingSystemVersion_Windows7,
diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp
index bfea41851..0cbd323de 100644
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -241,6 +241,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,
@@ -823,6 +826,12 @@ static OperatingSystem
 WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
 {
   switch(aWindowsVersion) {
+    case kWindowsXP:
+      return OperatingSystem::WindowsXP;
+    case kWindowsServer2003:
+      return OperatingSystem::WindowsServer2003;
+    case kWindowsVista:
+      return OperatingSystem::WindowsVista;
     case kWindows7:
       return OperatingSystem::Windows7;
     case kWindows8:
@@ -851,6 +860,11 @@ GfxInfo::GetGfxDriverInfo()
     /*
      * NVIDIA entries
      */
+    APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_LESS_THAN_OR_EQUAL, V(6,14,11,8745), "FEATURE_FAILURE_NV_XP", "nVidia driver > 187.45" );
+
     /*
      * The last 5 digit of the NVIDIA driver version maps to the version that
      * NVIDIA uses. The minor version (15, 16, 17) corresponds roughtly to the
@@ -861,17 +875,33 @@ GfxInfo::GetGfxDriverInfo()
      * 187.45 (late October 2009) and earlier contain a bug which can cause us
      * to crash on shutdown.
      */
+    APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_LESS_THAN_OR_EQUAL, V(8,15,11,8745),
+      "FEATURE_FAILURE_NV_VISTA_15", "nVidia driver > 187.45" );
     APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Windows7,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_LESS_THAN_OR_EQUAL, V(8,15,11,8745),
       "FEATURE_FAILURE_NV_W7_15", "nVidia driver > 187.45" );
+    APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsVista,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_BETWEEN_INCLUSIVE_START, V(8,16,10,0000), V(8,16,11,8745),
+      "FEATURE_FAILURE_NV_VISTA_16", "nVidia driver > 187.45" );
     APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::Windows7,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_BETWEEN_INCLUSIVE_START, V(8,16,10,0000), V(8,16,11,8745),
       "FEATURE_FAILURE_NV_W7_16", "nVidia driver > 187.45" );
     // Telemetry doesn't show any driver in this range so it might not even be required.
+    APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsVista,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_BETWEEN_INCLUSIVE_START, V(8,17,10,0000), V(8,17,11,8745),
+      "FEATURE_FAILURE_NV_VISTA_17", "nVidia driver > 187.45" );
+    // Telemetry doesn't show any driver in this range so it might not even be required.
     APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::Windows7,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
@@ -969,6 +999,13 @@ GfxInfo::GetGfxDriverInfo()
         nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,                                               \
         DRIVER_BUILD_ID_LESS_THAN, driverVer, ruleId )
 
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA500,   1006, "FEATURE_FAILURE_594877_1");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA900,   GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_594877_2");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA950,   1504, "FEATURE_FAILURE_594877_3");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA3150,  2124, "FEATURE_FAILURE_594877_4");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMAX3000, 1666, "FEATURE_FAILURE_594877_5");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelHDGraphicsToSandyBridge, 2202, "FEATURE_FAILURE_594877_6");
+
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA500,   2026, "FEATURE_FAILURE_594877_7");
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA900,   GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_594877_8");
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA950,   1930, "FEATURE_FAILURE_594877_9");
@@ -985,6 +1022,31 @@ GfxInfo::GetGfxDriverInfo()
       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_1180379");
 
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA500,   V(3,0,20,3200), "FEATURE_FAILURE_INTEL_1");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA900,   V(6,14,10,4764), "FEATURE_FAILURE_INTEL_2");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA950,   V(6,14,10,4926), "FEATURE_FAILURE_INTEL_3");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA3150,  V(6,14,10,5134), "FEATURE_FAILURE_INTEL_4");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX3000, V(6,14,10,5218), "FEATURE_FAILURE_INTEL_5");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX4500HD, V(6,14,10,4969), "FEATURE_FAILURE_INTEL_6");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelHDGraphicsToSandyBridge, V(6,14,10,4969), "FEATURE_FAILURE_INTEL_7");
+
+    // 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,
+      const_cast<nsAString&>(GfxDriverInfo::GetDeviceVendor(VendorIntel)),
+      const_cast<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_8", "6.14.10.5218");
+
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA500,   V(3,0,20,3200), "FEATURE_FAILURE_INTEL_9");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA900,   GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_10");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA950,   V(7,14,10,1504), "FEATURE_FAILURE_INTEL_11");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA3150,  V(7,14,10,1910), "FEATURE_FAILURE_INTEL_12");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMAX3000, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_13");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMAX4500HD, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_14");
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelHDGraphicsToSandyBridge, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_15");
+
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA500,   V(5,0,0,2026), "FEATURE_FAILURE_INTEL_16");
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA900,   GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_17");
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA950,   V(8,15,10,1930), "FEATURE_FAILURE_INTEL_18");
@@ -1238,6 +1300,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/KeyboardLayout.cpp b/widget/windows/KeyboardLayout.cpp
index 341a40c18..11f657874 100644
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -1363,6 +1363,34 @@ NativeKey::InitWithKeyChar()
         break;
       }
 
+      if (!CanComputeVirtualKeyCodeFromScanCode()) {
+        // The right control key and the right alt key are extended keys.
+        // Therefore, we never get VK_RCONTRL and VK_RMENU for the result of
+        // MapVirtualKeyEx() on WinXP or WinServer2003.
+        //
+        // If VK_SHIFT, VK_CONTROL or VK_MENU key message is caused by well
+        // known scan code, we should decide it as Right key.  Otherwise,
+        // decide it as Left key.
+        switch (mOriginalVirtualKeyCode) {
+          case VK_CONTROL:
+            mVirtualKeyCode =
+              mIsExtended && mScanCode == 0x1D ? VK_RCONTROL : VK_LCONTROL;
+            break;
+          case VK_MENU:
+            mVirtualKeyCode =
+              mIsExtended && mScanCode == 0x38 ? VK_RMENU : VK_LMENU;
+            break;
+          case VK_SHIFT:
+            // Neither left shift nor right shift is an extended key,
+            // let's use VK_LSHIFT for unknown mapping.
+            mVirtualKeyCode = VK_LSHIFT;
+            break;
+          default:
+            MOZ_CRASH("Unsupported mOriginalVirtualKeyCode");
+        }
+        break;
+      }
+
       NS_ASSERTION(!mVirtualKeyCode,
                    "mVirtualKeyCode has been computed already");
 
@@ -1419,6 +1447,11 @@ NativeKey::InitWithKeyChar()
       //       scancode, we cannot compute virtual keycode.  I.e., with such
       //       applications, we cannot generate proper KeyboardEvent.code value.
 
+      // We cannot compute the virtual key code from WM_CHAR message on WinXP
+      // if it's caused by an extended key.
+      if (!CanComputeVirtualKeyCodeFromScanCode()) {
+        break;
+      }
       mVirtualKeyCode = mOriginalVirtualKeyCode =
         ComputeVirtualKeyCodeFromScanCodeEx();
       NS_ASSERTION(mVirtualKeyCode, "Failed to compute virtual keycode");
@@ -1836,6 +1869,18 @@ NativeKey::GetKeyLocation() const
   }
 }
 
+bool
+NativeKey::CanComputeVirtualKeyCodeFromScanCode() const
+{
+  // Vista or later supports ScanCodeEx.
+  if (IsVistaOrLater()) {
+    return true;
+  }
+  // Otherwise, MapVirtualKeyEx() can compute virtual keycode only with
+  // non-extended key.
+  return !mIsExtended;
+}
+
 uint8_t
 NativeKey::ComputeVirtualKeyCodeFromScanCode() const
 {
@@ -1849,6 +1894,12 @@ NativeKey::ComputeVirtualKeyCodeFromScanCodeEx() const
   // MapVirtualKeyEx() has been improved for supporting extended keys since
   // Vista.  When we call it for mapping a scancode of an extended key and
   // a virtual keycode, we need to add 0xE000 to the scancode.
+  // On the other hand, neither WinXP nor WinServer2003 doesn't support 0xE000.
+  // Therefore, we have no way to get virtual keycode from scan code of
+  // extended keys.
+  if (NS_WARN_IF(!CanComputeVirtualKeyCodeFromScanCode())) {
+    return 0;
+  }
   return static_cast<uint8_t>(
            ::MapVirtualKeyEx(GetScanCodeWithExtendedFlag(), MAPVK_VSC_TO_VK_EX,
                              mKeyboardLayout));
@@ -1859,7 +1910,8 @@ NativeKey::ComputeScanCodeExFromVirtualKeyCode(UINT aVirtualKeyCode) const
 {
   return static_cast<uint16_t>(
            ::MapVirtualKeyEx(aVirtualKeyCode,
-                             MAPVK_VK_TO_VSC_EX,
+                             IsVistaOrLater() ? MAPVK_VK_TO_VSC_EX :
+                                                MAPVK_VK_TO_VSC,
                              mKeyboardLayout));
 }
 
@@ -4293,7 +4345,8 @@ KeyboardLayout::LoadLayout(HKL aLayout)
 
   if (MOZ_LOG_TEST(sKeyboardLayoutLogger, LogLevel::Verbose)) {
     static const UINT kExtendedScanCode[] = { 0x0000, 0xE000 };
-    static const UINT kMapType = MAPVK_VSC_TO_VK_EX;
+    static const UINT kMapType =
+      IsVistaOrLater() ? MAPVK_VSC_TO_VK_EX : MAPVK_VSC_TO_VK;
     MOZ_LOG(sKeyboardLayoutLogger, LogLevel::Verbose,
       ("Logging virtual keycode values for scancode (0x%p)...",
        mKeyboardLayout));
@@ -4305,6 +4358,11 @@ KeyboardLayout::LoadLayout(HKL aLayout)
         MOZ_LOG(sKeyboardLayoutLogger, LogLevel::Verbose,
           ("0x%04X, %s", scanCode, kVirtualKeyName[virtualKeyCode]));
       }
+      // XP and Server 2003 don't support 0xE0 prefix of the scancode.
+      // Therefore, we don't need to continue on them.
+      if (!IsVistaOrLater()) {
+        break;
+      }
     }
   }
 }
diff --git a/widget/windows/KeyboardLayout.h b/widget/windows/KeyboardLayout.h
index 70aacc80e..dd2ac0bfc 100644
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -559,6 +559,11 @@ private:
    */
   bool GetFollowingCharMessage(MSG& aCharMsg);
 
+  /**
+   * Whether the key event can compute virtual keycode from the scancode value.
+   */
+  bool CanComputeVirtualKeyCodeFromScanCode() const;
+
   /**
    * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK.
    */
diff --git a/widget/windows/LSPAnnotator.cpp b/widget/windows/LSPAnnotator.cpp
index 97f6e5b50..de4a40d2a 100644
--- a/widget/windows/LSPAnnotator.cpp
+++ b/widget/windows/LSPAnnotator.cpp
@@ -11,6 +11,11 @@
  * on machines with several LSPs.
  */
 
+#if _WIN32_WINNT < 0x0600
+// Redefining _WIN32_WINNT for some Vista APIs that we call
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
 #include "nsICrashReporter.h"
 #include "nsISupportsImpl.h"
 #include "nsServiceManagerUtils.h"
diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp
index 7224126b8..fb0505aa3 100644
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -5762,7 +5762,8 @@ TSFTextStore::Initialize()
     return;
   }
 
-  bool enableTsf = Preferences::GetBool(kPrefNameEnableTSF, false);
+  bool enableTsf =
+    IsVistaOrLater() && Preferences::GetBool(kPrefNameEnableTSF, false);
   MOZ_LOG(sTextStoreLog, LogLevel::Info,
     ("  TSFTextStore::Initialize(), TSF is %s",
      enableTsf ? "enabled" : "disabled"));
diff --git a/widget/windows/TaskbarPreview.cpp b/widget/windows/TaskbarPreview.cpp
index 6c15df2e0..c897af021 100644
--- a/widget/windows/TaskbarPreview.cpp
+++ b/widget/windows/TaskbarPreview.cpp
@@ -28,9 +28,7 @@
 #include "mozilla/Telemetry.h"
 
 // Defined in dwmapi in a header that needs a higher numbered _WINNT #define
-#ifndef DWM_SIT_DISPLAYFRAME
 #define DWM_SIT_DISPLAYFRAME 0x1
-#endif
 
 namespace mozilla {
 namespace widget {
diff --git a/widget/windows/WinMouseScrollHandler.cpp b/widget/windows/WinMouseScrollHandler.cpp
index e157b1be2..10937ba51 100644
--- a/widget/windows/WinMouseScrollHandler.cpp
+++ b/widget/windows/WinMouseScrollHandler.cpp
@@ -992,7 +992,10 @@ MouseScrollHandler::SystemSettings::InitScrollChars()
                                      &mScrollChars, 0)) {
     MOZ_LOG(gMouseScrollLog, LogLevel::Info,
       ("MouseScroll::SystemSettings::InitScrollChars(): ::SystemParametersInfo("
-       "SPI_GETWHEELSCROLLCHARS) failed, this is unexpected on Vista or later"));
+       "SPI_GETWHEELSCROLLCHARS) failed, %s",
+       IsVistaOrLater() ?
+         "this is unexpected on Vista or later" :
+         "but on XP or earlier, this is not a problem"));
     // XXX Should we use DefaultScrollChars()?
     mScrollChars = 1;
   }
@@ -1078,7 +1081,7 @@ bool
 MouseScrollHandler::SystemSettings::IsOverridingSystemScrollSpeedAllowed()
 {
   return mScrollLines == DefaultScrollLines() &&
-         mScrollChars == DefaultScrollChars();
+         (!IsVistaOrLater() || mScrollChars == DefaultScrollChars());
 }
 
 /******************************************************************************
diff --git a/widget/windows/WinTaskbar.cpp b/widget/windows/WinTaskbar.cpp
index 530cfd5b9..698b7ec0e 100644
--- a/widget/windows/WinTaskbar.cpp
+++ b/widget/windows/WinTaskbar.cpp
@@ -34,6 +34,8 @@
 #include <propkey.h>
 #include <shellapi.h>
 
+const wchar_t kShellLibraryName[] =  L"shell32.dll";
+
 static NS_DEFINE_CID(kJumpListBuilderCID, NS_WIN_JUMPLISTBUILDER_CID);
 
 namespace {
@@ -75,14 +77,30 @@ SetWindowAppUserModelProp(mozIDOMWindow *aParent,
   if (!toplevelHWND)
     return NS_ERROR_INVALID_ARG;
 
-  RefPtr<IPropertyStore> pPropStore;
-  if (FAILED(SHGetPropertyStoreForWindow(toplevelHWND, IID_IPropertyStore,
-                                         getter_AddRefs(pPropStore)))) {
+  typedef HRESULT (WINAPI * SHGetPropertyStoreForWindowPtr)
+                    (HWND hwnd, REFIID riid, void** ppv);
+  SHGetPropertyStoreForWindowPtr funcGetProStore = nullptr;
+
+  HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
+  funcGetProStore = (SHGetPropertyStoreForWindowPtr)
+    GetProcAddress(hDLL, "SHGetPropertyStoreForWindow");
+
+  if (!funcGetProStore) {
+    FreeLibrary(hDLL);
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  IPropertyStore* pPropStore;
+  if (FAILED(funcGetProStore(toplevelHWND,
+                             IID_PPV_ARGS(&pPropStore)))) {
+    FreeLibrary(hDLL);
     return NS_ERROR_INVALID_ARG;
   }
 
   PROPVARIANT pv;
   if (FAILED(InitPropVariantFromString(aIdentifier.get(), &pv))) {
+    pPropStore->Release();
+    FreeLibrary(hDLL);
     return NS_ERROR_UNEXPECTED;
   }
 
@@ -93,6 +111,8 @@ SetWindowAppUserModelProp(mozIDOMWindow *aParent,
   }
 
   PropVariantClear(&pv);
+  pPropStore->Release();
+  FreeLibrary(hDLL);
 
   return rv;
 }
@@ -319,18 +339,40 @@ WinTaskbar::GetDefaultGroupId(nsAString & aDefaultGroupId) {
 // (static) Called from AppShell
 bool
 WinTaskbar::RegisterAppUserModelID() {
+  if (!IsWin7OrLater())
+    return false;
+
+  SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nullptr;
+  bool retVal = false;
+
   nsAutoString uid;
   if (!GetAppUserModelID(uid))
     return false;
 
-  return SUCCEEDED(SetCurrentProcessExplicitAppUserModelID(uid.get()));
+  HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
+
+  funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
+                        GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
+
+  if (!funcAppUserModelID) {
+    ::FreeLibrary(hDLL);
+    return false;
+  }
+
+  if (SUCCEEDED(funcAppUserModelID(uid.get())))
+    retVal = true;
+
+  if (hDLL)
+    ::FreeLibrary(hDLL);
+
+  return retVal;
 }
 
 NS_IMETHODIMP
 WinTaskbar::GetAvailable(bool *aAvailable) {
   // ITaskbarList4::HrInit() may fail with shell extensions like blackbox
   // installed. Initialize early to return available=false in those cases.
-  *aAvailable = Initialize();
+  *aAvailable = IsWin7OrLater() && Initialize();
 
   return NS_OK;
 }
diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp
index 0a57ad439..149513b2f 100644
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -462,7 +462,7 @@ static NtTestAlertPtr sNtTestAlert = nullptr;
 void
 WinUtils::Initialize()
 {
-  if (!sDwmDll) {
+  if (!sDwmDll && IsVistaOrLater()) {
     sDwmDll = ::LoadLibraryW(kDwmLibraryName);
 
     if (sDwmDll) {
@@ -601,7 +601,7 @@ WinUtils::SystemScaleFactor()
   return systemScale;
 }
 
-#if WINVER < 0x603
+#ifndef WM_DPICHANGED
 typedef enum {
   MDT_EFFECTIVE_DPI = 0,
   MDT_ANGULAR_DPI = 1,
@@ -628,14 +628,16 @@ GETPROCESSDPIAWARENESSPROC sGetProcessDpiAwareness;
 static bool
 SlowIsPerMonitorDPIAware()
 {
-  // Intentionally leak the handle.
-  HMODULE shcore =
-    LoadLibraryEx(L"shcore", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
-  if (shcore) {
-    sGetDpiForMonitor =
-      (GETDPIFORMONITORPROC) GetProcAddress(shcore, "GetDpiForMonitor");
-    sGetProcessDpiAwareness =
-      (GETPROCESSDPIAWARENESSPROC) GetProcAddress(shcore, "GetProcessDpiAwareness");
+  if (IsVistaOrLater()) {
+    // Intentionally leak the handle.
+    HMODULE shcore =
+      LoadLibraryEx(L"shcore", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+    if (shcore) {
+      sGetDpiForMonitor =
+        (GETDPIFORMONITORPROC) GetProcAddress(shcore, "GetDpiForMonitor");
+      sGetProcessDpiAwareness =
+        (GETPROCESSDPIAWARENESSPROC) GetProcAddress(shcore, "GetProcessDpiAwareness");
+    }
   }
   PROCESS_DPI_AWARENESS dpiAwareness;
   return sGetDpiForMonitor && sGetProcessDpiAwareness &&
@@ -758,7 +760,7 @@ static DWORD
 GetWaitFlags()
 {
   DWORD result = MWMO_INPUTAVAILABLE;
-  if (XRE_IsContentProcess()) {
+  if (IsVistaOrLater() && XRE_IsContentProcess()) {
     result |= MWMO_ALERTABLE;
   }
   return result;
@@ -1876,7 +1878,7 @@ WinUtils::IsTouchDeviceSupportPresent()
 uint32_t
 WinUtils::GetMaxTouchPoints()
 {
-  if (IsTouchDeviceSupportPresent()) {
+  if (IsWin7OrLater() && IsTouchDeviceSupportPresent()) {
     return GetSystemMetrics(SM_MAXIMUMTOUCHES);
   }
   return 0;
@@ -1891,6 +1893,11 @@ typedef DWORD (WINAPI * GetFinalPathNameByHandlePtr)(HANDLE hFile,
 bool
 WinUtils::ResolveJunctionPointsAndSymLinks(std::wstring& aPath)
 {
+  // Users folder was introduced with Vista.
+  if (!IsVistaOrLater()) {
+    return true;
+  }
+
   wchar_t path[MAX_PATH] = { 0 };
 
   nsAutoHandle handle(
@@ -2018,19 +2025,21 @@ WinUtils::GetAppInitDLLs(nsAString& aOutput)
   }
   nsAutoRegKey key(hkey);
   LONG status;
-  const wchar_t kLoadAppInitDLLs[] = L"LoadAppInit_DLLs";
-  DWORD loadAppInitDLLs = 0;
-  DWORD loadAppInitDLLsLen = sizeof(loadAppInitDLLs);
-  status = RegQueryValueExW(hkey, kLoadAppInitDLLs, nullptr,
-                            nullptr, (LPBYTE)&loadAppInitDLLs,
-                            &loadAppInitDLLsLen);
-  if (status != ERROR_SUCCESS) {
-    return false;
-  }
-  if (!loadAppInitDLLs) {
-    // If loadAppInitDLLs is zero then AppInit_DLLs is disabled.
-    // In this case we'll return true along with an empty output string.
-    return true;
+  if (IsVistaOrLater()) {
+    const wchar_t kLoadAppInitDLLs[] = L"LoadAppInit_DLLs";
+    DWORD loadAppInitDLLs = 0;
+    DWORD loadAppInitDLLsLen = sizeof(loadAppInitDLLs);
+    status = RegQueryValueExW(hkey, kLoadAppInitDLLs, nullptr,
+                              nullptr, (LPBYTE)&loadAppInitDLLs,
+                              &loadAppInitDLLsLen);
+    if (status != ERROR_SUCCESS) {
+      return false;
+    }
+    if (!loadAppInitDLLs) {
+      // If loadAppInitDLLs is zero then AppInit_DLLs is disabled.
+      // In this case we'll return true along with an empty output string.
+      return true;
+    }
   }
   DWORD numBytes = 0;
   const wchar_t kAppInitDLLs[] = L"AppInit_DLLs";
diff --git a/widget/windows/WindowsUIUtils.cpp b/widget/windows/WindowsUIUtils.cpp
index 1c270b5ec..223511859 100644
--- a/widget/windows/WindowsUIUtils.cpp
+++ b/widget/windows/WindowsUIUtils.cpp
@@ -5,8 +5,7 @@
 
 #include <windows.h>
 #include <winsdkver.h>
-#include <wrl.h>
-
+#include "mozwrlbase.h"
 #include "nsServiceManagerUtils.h"
 
 #include "WindowsUIUtils.h"
@@ -180,3 +179,4 @@ WindowsUIUtils::UpdateTabletModeState()
 
   return NS_OK;
 }
+
diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp
index 02ec3b2fe..fc45968ae 100644
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -1148,7 +1148,8 @@ nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG )
   const char *shortcutFormatStr;
   int totalLen;
   nsCString path;
-  if (!Preferences::GetBool(kShellIconPref, true)) {
+  if (!Preferences::GetBool(kShellIconPref, true) ||
+      !IsVistaOrLater()) {
     shortcutFormatStr = "[InternetShortcut]\r\nURL=%s\r\n";
     const int formatLen = strlen(shortcutFormatStr) - 2;  // don't include %s
     totalLen = formatLen + asciiUrl.Length();  // don't include null character
diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp
index 4e942968a..53857cf5e 100644
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -28,6 +28,7 @@
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.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 740f07a7d..90d8c15bc 100644
--- a/widget/windows/nsFilePicker.h
+++ b/widget/windows/nsFilePicker.h
@@ -9,6 +9,17 @@
 
 #include <windows.h>
 
+// For Vista IFileDialog interfaces which aren't exposed
+// unless _WIN32_WINNT >= _WIN32_WINNT_LONGHORN.
+#if _WIN32_WINNT < _WIN32_WINNT_LONGHORN
+#define _WIN32_WINNT_bak _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_LONGHORN
+#define _WIN32_IE_bak _WIN32_IE
+#undef _WIN32_IE
+#define _WIN32_IE _WIN32_IE_IE70
+#endif
+
 #include "nsIFile.h"
 #include "nsITimer.h"
 #include "nsISimpleEnumerator.h"
@@ -76,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;
@@ -130,4 +154,11 @@ protected:
   DWORD                  mFDECookie;
 };
 
+#if defined(_WIN32_WINNT_bak)
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_bak
+#undef _WIN32_IE
+#define _WIN32_IE _WIN32_IE_bak
+#endif
+
 #endif // nsFilePicker_h__
diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp
index 06eee3771..e649802b1 100644
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -32,8 +32,12 @@ nsLookAndFeel::GetOperatingSystemVersion()
     version = eOperatingSystemVersion_Windows10;
   } else if (IsWin8OrLater()) {
     version = eOperatingSystemVersion_Windows8;
-  } else {
+  } else if (IsWin7OrLater()) {
     version = eOperatingSystemVersion_Windows7;
+  } else if (IsVistaOrLater()) {
+    version = eOperatingSystemVersion_WindowsVista;
+  } else {
+    version = eOperatingSystemVersion_WindowsXP;
   }
 
   return version;
@@ -179,7 +183,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
       idx = COLOR_HIGHLIGHT;
       break;
     case eColorID__moz_menubarhovertext:
-      if (!IsAppThemed()) {
+      if (!IsVistaOrLater() || !IsAppThemed())
+      {
         idx = nsUXThemeData::sFlatMenus ?
                 COLOR_HIGHLIGHTTEXT :
                 COLOR_MENUTEXT;
@@ -187,7 +192,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
       }
       // Fall through
     case eColorID__moz_menuhovertext:
-      if (IsAppThemed()) {
+      if (IsVistaOrLater() && IsAppThemed())
+      {
         res = ::GetColorFromTheme(eUXMenu,
                                   MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
@@ -279,7 +285,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
       aColor = NS_RGB(0, 0, 0);
       return NS_OK;
     case eColorID__moz_win_mediatext:
-      if (IsAppThemed()) {
+      if (IsVistaOrLater() && IsAppThemed()) {
         res = ::GetColorFromTheme(eUXMediaToolbar,
                                   TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
@@ -289,7 +295,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_win_communicationstext:
-      if (IsAppThemed()) {
+      if (IsVistaOrLater() && IsAppThemed())
+      {
         res = ::GetColorFromTheme(eUXCommunicationsToolbar,
                                   TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
diff --git a/widget/windows/nsLookAndFeel.h b/widget/windows/nsLookAndFeel.h
index a77808322..6200541f5 100644
--- a/widget/windows/nsLookAndFeel.h
+++ b/widget/windows/nsLookAndFeel.h
@@ -5,7 +5,6 @@
 
 #ifndef __nsLookAndFeel
 #define __nsLookAndFeel
-
 #include "nsXPLookAndFeel.h"
 #include "nsIWindowsRegKey.h"
 
@@ -29,6 +28,18 @@
 #ifndef SM_SYSTEMDOCKED
 #define SM_CONVERTIBLESLATEMODE 0x00002003
 #define SM_SYSTEMDOCKED         0x00002004
+typedef enum _AR_STATE
+{
+  AR_ENABLED        = 0x0,
+  AR_DISABLED       = 0x1,
+  AR_SUPPRESSED     = 0x2,
+  AR_REMOTESESSION  = 0x4,
+  AR_MULTIMON       = 0x8,
+  AR_NOSENSOR       = 0x10,
+  AR_NOT_SUPPORTED  = 0x20,
+  AR_DOCKED         = 0x40,
+  AR_LAPTOP         = 0x80
+} AR_STATE, *PAR_STATE;
 #endif
 
 class nsLookAndFeel: public nsXPLookAndFeel {
diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp
index 8950dcf90..4ff6b0af9 100644
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -39,6 +39,7 @@
 #include "nsUXThemeConstants.h"
 #include <algorithm>
 
+using mozilla::IsVistaOrLater;
 using namespace mozilla;
 using namespace mozilla::widget;
 
@@ -300,6 +301,10 @@ DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, int aState,
  *  aero basic max          0        2        1        2
  *  aero basic close        1        2        1        2
  *
+ *  xp theme min            0        2        0        2
+ *  xp theme max            0        2        1        2
+ *  xp theme close          1        2        2        2
+ *
  *  'cold' button padding - generic button padding, should
  *  be handled in css.
  *                       left      top    right   bottom
@@ -310,11 +315,16 @@ DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, int aState,
  *  aero basic min          0        0        1        0
  *  aero basic max          1        0        0        0
  *  aero basic close        0        0        0        0
+ *
+ *  xp theme min            0        0        1        0
+ *  xp theme max            1        0        0        0
+ *  xp theme close          0        0        0        0
  */
 
 enum CaptionDesktopTheme {
   CAPTION_CLASSIC = 0,
   CAPTION_BASIC,
+  CAPTION_XPTHEME,
 };
 
 enum CaptionButton {
@@ -348,6 +358,8 @@ AddPaddingRect(LayoutDeviceIntSize* aSize, CaptionButton button) {
   RECT offset;
   if (!IsAppThemed())
     offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
+  else if (!IsVistaOrLater())
+    offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   else
     offset = buttonData[CAPTION_BASIC].hotPadding[button];
   aSize->width += offset.left + offset.right;
@@ -361,6 +373,8 @@ OffsetBackgroundRect(RECT& rect, CaptionButton button) {
   RECT offset;
   if (!IsAppThemed())
     offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
+  else if (!IsVistaOrLater())
+    offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   else
     offset = buttonData[CAPTION_BASIC].hotPadding[button];
   rect.left += offset.left;
@@ -405,7 +419,9 @@ OffsetBackgroundRect(RECT& rect, CaptionButton button) {
 static const double kProgressDeterminateTimeSpan = 3.0;
 static const double kProgressIndeterminateTimeSpan = 5.0;
 // The width of the overlay used to animate the horizontal progress bar (Vista and later).
-static const int32_t kProgressHorizontalOverlaySize = 120;
+static const int32_t kProgressHorizontalVistaOverlaySize = 120;
+// The width of the overlay used for the horizontal indeterminate progress bars on XP.
+static const int32_t kProgressHorizontalXPOverlaySize = 55;
 // The height of the overlay used to animate the vertical progress bar (Vista and later).
 static const int32_t kProgressVerticalOverlaySize = 45;
 // The height of the overlay used for the vertical indeterminate progress bar (Vista and later).
@@ -419,8 +435,18 @@ static const int32_t kProgressClassicOverlaySize = 40;
  */
 static int32_t
 GetProgressOverlayStyle(bool aIsVertical)
-{
-  return aIsVertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
+{ 
+  if (aIsVertical) {
+    if (IsVistaOrLater()) {
+      return PP_MOVEOVERLAYVERT;
+    }
+    return PP_CHUNKVERT;
+  } else {
+    if (IsVistaOrLater()) {
+      return PP_MOVEOVERLAY;
+    }
+    return PP_CHUNK;
+  }
 }
 
 /*
@@ -431,11 +457,14 @@ GetProgressOverlayStyle(bool aIsVertical)
 static int32_t
 GetProgressOverlaySize(bool aIsVertical, bool aIsIndeterminate)
 {
-  if (aIsVertical) {
-    return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize
-                            : kProgressVerticalOverlaySize;
+  if (IsVistaOrLater()) {
+    if (aIsVertical) {
+      return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize
+                              : kProgressVerticalOverlaySize;
+    }
+    return kProgressHorizontalVistaOverlaySize;
   }
-  return kProgressHorizontalOverlaySize;
+  return kProgressHorizontalXPOverlaySize;
 }
 
 /*
@@ -524,6 +553,87 @@ nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame* aFrame,
   return overlayRect;
 }
 
+/*
+ * DrawChunkProgressMeter - renders an xp style chunked progress meter. Called
+ * by DrawProgressMeter.
+ *
+ * @param aTheme       progress theme handle
+ * @param aHdc         hdc returned by gfxWindowsNativeDrawing
+ * @param aPart        the PP_X progress part
+ * @param aState       the theme state
+ * @param aFrame       the elements frame
+ * @param aWidgetRect  bounding rect for the widget
+ * @param aClipRect    dirty rect that needs drawing.
+ * @param aAppUnits    app units per device pixel
+ * @param aIsIndeterm  is an indeterminate progress?
+ * @param aIsVertical  render a vertical progress?
+ * @param aIsRtl       direction is rtl
+ */
+static void
+DrawChunkProgressMeter(HTHEME aTheme, HDC aHdc, int aPart,
+                       int aState, nsIFrame* aFrame, RECT* aWidgetRect,
+                       RECT* aClipRect, gfxFloat aAppUnits, bool aIsIndeterm,
+                       bool aIsVertical, bool aIsRtl)
+{
+  NS_ASSERTION(aTheme, "Bad theme.");
+  NS_ASSERTION(aHdc, "Bad hdc.");
+  NS_ASSERTION(aWidgetRect, "Bad rect.");
+  NS_ASSERTION(aClipRect, "Bad clip rect.");
+  NS_ASSERTION(aFrame, "Bad frame.");
+
+  // For horizontal meters, the theme lib paints the right graphic but doesn't
+  // paint the chunks, so we do that manually. For vertical meters, the theme
+  // library draws everything correctly.
+  if (aIsVertical) {
+    DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
+    return;
+  }
+
+  // query for the proper chunk metrics
+  int chunkSize, spaceSize;
+  if (FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
+                            TMT_PROGRESSCHUNKSIZE, &chunkSize)) ||
+      FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
+                            TMT_PROGRESSSPACESIZE, &spaceSize))) {
+    DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
+    return;
+  }
+
+  // render chunks
+  if (!aIsRtl || aIsIndeterm) {
+    for (int chunk = aWidgetRect->left; chunk <= aWidgetRect->right;
+         chunk += (chunkSize+spaceSize)) {
+      if (!aIsIndeterm && ((chunk + chunkSize) > aWidgetRect->right)) {
+        // aWidgetRect->right represents the end of the meter. Partial blocks
+        // don't get rendered with one exception, so exit here if we don't have
+        // a full chunk to draw.
+        // The above is true *except* when the meter is at 100% fill, in which
+        // case Windows renders any remaining partial block. Query the parent
+        // frame to find out if we're at 100%.
+        if (!IsProgressMeterFilled(aFrame)) {
+          break;
+        }
+      }
+      RECT bounds =
+        { chunk, aWidgetRect->top, chunk + chunkSize, aWidgetRect->bottom };
+      DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
+    }
+  } else {
+    // rtl needs to grow in the opposite direction to look right.
+    for (int chunk = aWidgetRect->right; chunk >= aWidgetRect->left;
+         chunk -= (chunkSize+spaceSize)) {
+      if ((chunk - chunkSize) < aWidgetRect->left) {
+        if (!IsProgressMeterFilled(aFrame)) {
+          break;
+        }
+      }
+      RECT bounds =
+        { chunk - chunkSize, aWidgetRect->top, chunk, aWidgetRect->bottom };
+      DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
+    }
+  }
+}
+
 /*
  * DrawProgressMeter - render an appropriate progress meter based on progress
  * meter style, orientation, and os. Note, this does not render the underlying
@@ -543,7 +653,8 @@ void
 nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
                                           HANDLE aTheme, HDC aHdc,
                                           int aPart, int aState,
-                                          RECT* aWidgetRect, RECT* aClipRect)
+                                          RECT* aWidgetRect, RECT* aClipRect,
+                                          gfxFloat aAppUnits)
 {
   if (!aFrame || !aTheme || !aHdc)
     return;
@@ -554,6 +665,12 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
   RECT adjWidgetRect, adjClipRect;
   adjWidgetRect = *aWidgetRect;
   adjClipRect = *aClipRect;
+  if (!IsVistaOrLater()) {
+    // Adjust clipping out by one pixel. XP progress meters are inset,
+    // Vista+ are not.
+    InflateRect(&adjWidgetRect, 1, 1);
+    InflateRect(&adjClipRect, 1, 1);
+  }
 
   nsIFrame* parentFrame = aFrame->GetParent();
   if (!parentFrame) {
@@ -568,13 +685,20 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
   bool indeterminate = IsIndeterminateProgress(parentFrame, eventStates);
   bool animate = indeterminate;
 
-  // Vista and up progress meter is fill style, rendered here. We render
-  // the pulse overlay in the follow up section below.
-  DrawThemeBackground(aTheme, aHdc, aPart, aState,
-                      &adjWidgetRect, &adjClipRect);
-  if (!IsProgressMeterFilled(aFrame)) {
-    animate = true;
-  }
+  if (IsVistaOrLater()) {
+    // Vista and up progress meter is fill style, rendered here. We render
+    // the pulse overlay in the follow up section below.
+    DrawThemeBackground(aTheme, aHdc, aPart, aState,
+                        &adjWidgetRect, &adjClipRect);
+    if (!IsProgressMeterFilled(aFrame)) {
+      animate = true;
+    }
+  } else if (!indeterminate) {
+    // XP progress meters are 'chunk' style.
+    DrawChunkProgressMeter(aTheme, aHdc, aPart, aState, aFrame,
+                           &adjWidgetRect, &adjClipRect, aAppUnits,
+                           indeterminate, vertical, IsFrameRTL(aFrame));
+  }    
 
   if (animate) {
     // Indeterminate rendering
@@ -582,8 +706,14 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
     RECT overlayRect =
       CalculateProgressOverlayRect(aFrame, &adjWidgetRect, vertical,
                                    indeterminate, false);
-    DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect,
-                        &adjClipRect);
+    if (IsVistaOrLater()) {
+      DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect,
+                          &adjClipRect);
+    } else {
+      DrawChunkProgressMeter(aTheme, aHdc, overlayPart, aState, aFrame,
+                             &overlayRect, &adjClipRect, aAppUnits,
+                             indeterminate, vertical, IsFrameRTL(aFrame));
+    }
 
     if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) {
       NS_WARNING("unable to animate progress widget!");
@@ -594,6 +724,15 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
 HANDLE
 nsNativeThemeWin::GetTheme(uint8_t aWidgetType)
 { 
+  if (!IsVistaOrLater()) {
+    // On XP or earlier, render dropdowns as textfields;
+    // doing it the right way works fine with the MS themes,
+    // but breaks on a lot of custom themes (presumably because MS
+    // apps do the textfield border business as well).
+    if (aWidgetType == NS_THEME_MENULIST)
+      aWidgetType = NS_THEME_TEXTFIELD;
+  }
+
   switch (aWidgetType) {
     case NS_THEME_BUTTON:
     case NS_THEME_RADIO:
@@ -606,7 +745,9 @@ nsNativeThemeWin::GetTheme(uint8_t aWidgetType)
     case NS_THEME_FOCUS_OUTLINE:
       return nsUXThemeData::GetTheme(eUXEdit);
     case NS_THEME_TOOLTIP:
-      return nsUXThemeData::GetTheme(eUXTooltip);
+      // XP/2K3 should force a classic treatment of tooltips
+      return !IsVistaOrLater() ?
+        nullptr : nsUXThemeData::GetTheme(eUXTooltip);
     case NS_THEME_TOOLBOX:
       return nsUXThemeData::GetTheme(eUXRebar);
     case NS_THEME_WIN_MEDIA_TOOLBOX:
@@ -733,6 +874,12 @@ nsresult
 nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType, 
                                        int32_t& aPart, int32_t& aState)
 {
+  if (!IsVistaOrLater()) {
+    // See GetTheme
+    if (aWidgetType == NS_THEME_MENULIST)
+      aWidgetType = NS_THEME_TEXTFIELD;
+  }
+
   switch (aWidgetType) {
     case NS_THEME_BUTTON: {
       aPart = BP_BUTTON;
@@ -805,43 +952,63 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
     case NS_THEME_TEXTFIELD_MULTILINE: {
       EventStates eventState = GetContentState(aFrame, aWidgetType);
 
-      /* Note: the NOSCROLL type has a rounded corner in each corner.  The more
-       * specific HSCROLL, VSCROLL, HVSCROLL types have side and/or top/bottom
-       * edges rendered as straight horizontal lines with sharp corners to
-       * accommodate a scrollbar.  However, the scrollbar gets rendered on top
-       * of this for us, so we don't care, and can just use NOSCROLL here.
-       */
-      aPart = TFP_EDITBORDER_NOSCROLL;
+      if (IsVistaOrLater()) {
+        /* Note: the NOSCROLL type has a rounded corner in each
+         * corner.  The more specific HSCROLL, VSCROLL, HVSCROLL types
+         * have side and/or top/bottom edges rendered as straight
+         * horizontal lines with sharp corners to accommodate a
+         * scrollbar.  However, the scrollbar gets rendered on top of
+         * this for us, so we don't care, and can just use NOSCROLL
+         * here.
+         */
+        aPart = TFP_EDITBORDER_NOSCROLL;
 
-      if (!aFrame) {
-        aState = TFS_EDITBORDER_NORMAL;
-      } else if (IsDisabled(aFrame, eventState)) {
-        aState = TFS_EDITBORDER_DISABLED;
-      } else if (IsReadOnly(aFrame)) {
-        /* no special read-only state */
-        aState = TFS_EDITBORDER_NORMAL;
-      } else {
-        nsIContent* content = aFrame->GetContent();
+        if (!aFrame) {
+          aState = TFS_EDITBORDER_NORMAL;
+        } else if (IsDisabled(aFrame, eventState)) {
+          aState = TFS_EDITBORDER_DISABLED;
+        } else if (IsReadOnly(aFrame)) {
+          /* no special read-only state */
+          aState = TFS_EDITBORDER_NORMAL;
+        } else {
+          nsIContent* content = aFrame->GetContent();
 
-        /* XUL textboxes don't get focused themselves, because they have child
-         * html:input.. but we can check the XUL focused attributes on them
-         */
-        if (content && content->IsXULElement() && IsFocused(aFrame))
-          aState = TFS_EDITBORDER_FOCUSED;
-        else if (eventState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS))
-          aState = TFS_EDITBORDER_FOCUSED;
-        else if (eventState.HasState(NS_EVENT_STATE_HOVER))
-          aState = TFS_EDITBORDER_HOVER;
+          /* XUL textboxes don't get focused themselves, because they have child
+           * html:input.. but we can check the XUL focused attributes on them
+           */
+          if (content && content->IsXULElement() && IsFocused(aFrame))
+            aState = TFS_EDITBORDER_FOCUSED;
+          else if (eventState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS))
+            aState = TFS_EDITBORDER_FOCUSED;
+          else if (eventState.HasState(NS_EVENT_STATE_HOVER))
+            aState = TFS_EDITBORDER_HOVER;
+          else
+            aState = TFS_EDITBORDER_NORMAL;
+        }
+      } else {
+        aPart = TFP_TEXTFIELD;
+        
+        if (!aFrame)
+          aState = TS_NORMAL;
+        else if (IsDisabled(aFrame, eventState))
+          aState = TS_DISABLED;
+        else if (IsReadOnly(aFrame))
+          aState = TFS_READONLY;
         else
-          aState = TFS_EDITBORDER_NORMAL;
+          aState = StandardGetState(aFrame, aWidgetType, true);
       }
 
       return NS_OK;
     }
     case NS_THEME_FOCUS_OUTLINE: {
-      // XXX the EDITBORDER values don't respect DTBG_OMITCONTENT
-      aPart = TFP_TEXTFIELD; //TFP_EDITBORDER_NOSCROLL;
-      aState = TS_FOCUSED; //TFS_EDITBORDER_FOCUSED;
+      if (IsVistaOrLater()) {
+        // XXX the EDITBORDER values don't respect DTBG_OMITCONTENT
+        aPart = TFP_TEXTFIELD; //TFP_EDITBORDER_NOSCROLL;
+        aState = TS_FOCUSED; //TFS_EDITBORDER_FOCUSED;
+      } else {
+        aPart = TFP_TEXTFIELD;
+        aState = TS_FOCUSED;
+      }
       return NS_OK;
     }
     case NS_THEME_TOOLTIP: {
@@ -865,9 +1032,11 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
       nsIFrame* parentFrame = aFrame->GetParent();
       if (aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL ||
           IsVerticalProgress(parentFrame)) {
-        aPart = PP_FILLVERT;
+        aPart = IsVistaOrLater() ?
+          PP_FILLVERT : PP_CHUNKVERT;
       } else {
-        aPart = PP_FILL;
+        aPart = IsVistaOrLater() ?
+          PP_FILL : PP_CHUNK;
       }
 
       aState = PBBVS_NORMAL;
@@ -931,7 +1100,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
           aState += TS_ACTIVE;
         else if (eventState.HasState(NS_EVENT_STATE_HOVER))
           aState += TS_HOVER;
-        else if (parentState.HasState(NS_EVENT_STATE_HOVER))
+        else if (IsVistaOrLater() &&
+                 parentState.HasState(NS_EVENT_STATE_HOVER))
           aState = (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP) + SP_BUTTON_IMPLICIT_HOVER_BASE;
         else
           aState += TS_NORMAL;
@@ -1034,7 +1204,14 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
     case NS_THEME_SCROLLBAR:
     case NS_THEME_SCROLLBAR_SMALL: {
       aState = 0;
-      aPart = RP_BACKGROUND;
+      if (IsVistaOrLater()) {
+        // On vista, they have a part
+        aPart = RP_BACKGROUND;
+      } else {
+        // Otherwise, they don't.  (But I bet
+        // RP_BACKGROUND would work here, too);
+        aPart = 0;
+      }
       return NS_OK;
     }
     case NS_THEME_TOOLBAR: {
@@ -1159,7 +1336,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
         aFrame = parentFrame;
 
       EventStates eventState = GetContentState(aFrame, aWidgetType);
-      aPart = CBP_DROPMARKER_VISTA;
+      aPart = IsVistaOrLater() ?
+        CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
 
       // For HTML controls with author styling, we should fall
       // back to the old dropmarker style to avoid clashes with
@@ -1179,25 +1357,28 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
       else
         isOpen = IsOpenButton(aFrame);
 
-      if (isHTML || IsMenuListEditable(aFrame)) {
-        if (isOpen) {
-          /* Hover is propagated, but we need to know whether we're hovering
-           * just the combobox frame, not the dropdown frame. But, we can't get
-           * that information, since hover is on the content node, and they
-           * share the same content node.  So, instead, we cheat -- if the
-           * dropdown is open, we always show the hover state.  This looks fine
-           * in practice.
+      if (IsVistaOrLater()) {
+        if (isHTML || IsMenuListEditable(aFrame)) {
+          if (isOpen) {
+            /* Hover is propagated, but we need to know whether we're
+             * hovering just the combobox frame, not the dropdown frame.
+             * But, we can't get that information, since hover is on the
+             * content node, and they share the same content node.  So,
+             * instead, we cheat -- if the dropdown is open, we always
+             * show the hover state.  This looks fine in practice.
+             */
+            aState = TS_HOVER;
+            return NS_OK;
+          }
+        } else {
+          /* On Vista, the dropdown indicator on a menulist button in  
+           * chrome is not given a hover effect. When the frame isn't
+           * isn't HTML content, we cheat and force the dropdown state
+           * to be normal. (Bug 430434)
            */
-          aState = TS_HOVER;
+          aState = TS_NORMAL;
           return NS_OK;
         }
-      } else {
-        /* The dropdown indicator on a menulist button in chrome is not given a
-         * hover effect. When the frame isn't isn't HTML content, we cheat and
-         * force the dropdown state to be normal. (Bug 430434)
-         */
-        aState = TS_NORMAL;
-        return NS_OK;
       }
 
       aState = TS_NORMAL;
@@ -1698,7 +1879,7 @@ RENDER_AGAIN:
   else if (aWidgetType == NS_THEME_PROGRESSCHUNK ||
            aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL) {
     DrawThemedProgressMeter(aFrame, aWidgetType, theme, hdc, part, state,
-                            &widgetRect, &clipRect);
+                            &widgetRect, &clipRect, p2a);
   }
   else if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
     // Inflate 'widgetRect' with the focus outline size.
@@ -1964,39 +2145,41 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
     return ok;
   }
 
-  if (aWidgetType == NS_THEME_NUMBER_INPUT ||
-      aWidgetType == NS_THEME_TEXTFIELD ||
-      aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
-      aWidgetType == NS_THEME_MENULIST)
-  {
-    // If we have author-specified padding for these elements, don't do the
-    // fixups below.
-    if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
-      return false;
-  }
+  if (IsVistaOrLater()) {
+    if (aWidgetType == NS_THEME_NUMBER_INPUT ||
+        aWidgetType == NS_THEME_TEXTFIELD ||
+        aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
+        aWidgetType == NS_THEME_MENULIST)
+    {
+      /* If we have author-specified padding for these elements, don't do the fixups below */
+      if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
+        return false;
+    }
 
-  /* textfields need extra pixels on all sides, otherwise they wrap their
-   * content too tightly.  The actual border is drawn 1px inside the specified
-   * rectangle, so Gecko will end up making the contents look too small.
-   * Instead, we add 2px padding for the contents and fix this. (Used to be 1px
-   * added, see bug 430212)
-   */
-  if (aWidgetType == NS_THEME_NUMBER_INPUT ||
-      aWidgetType == NS_THEME_TEXTFIELD ||
-      aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
-    aResult->top = aResult->bottom = 2;
-    aResult->left = aResult->right = 2;
-    ScaleForFrameDPI(aResult, aFrame);
-    return ok;
-  } else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_MENULIST) {
-    /* For content menulist controls, we need an extra pixel so that we have
-     * room to draw our focus rectangle stuff. Otherwise, the focus rect might
-     * overlap the control's border.
+    /* textfields need extra pixels on all sides, otherwise they
+     * wrap their content too tightly.  The actual border is drawn 1px
+     * inside the specified rectangle, so Gecko will end up making the
+     * contents look too small.  Instead, we add 2px padding for the
+     * contents and fix this. (Used to be 1px added, see bug 430212)
      */
-    aResult->top = aResult->bottom = 1;
-    aResult->left = aResult->right = 1;
-    ScaleForFrameDPI(aResult, aFrame);
-    return ok;
+    if (aWidgetType == NS_THEME_NUMBER_INPUT ||
+        aWidgetType == NS_THEME_TEXTFIELD ||
+        aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
+      aResult->top = aResult->bottom = 2;
+      aResult->left = aResult->right = 2;
+      ScaleForFrameDPI(aResult, aFrame);
+      return ok;
+    } else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_MENULIST) {
+      /* For content menulist controls, we need an extra pixel so
+       * that we have room to draw our focus rectangle stuff.
+       * Otherwise, the focus rect might overlap the control's
+       * border.
+       */
+      aResult->top = aResult->bottom = 1;
+      aResult->left = aResult->right = 1;
+      ScaleForFrameDPI(aResult, aFrame);
+      return ok;
+    }
   }
 
   int32_t right, left, top, bottom;
@@ -2061,21 +2244,23 @@ nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext,
    * a border only shows up if the widget is being hovered.
    */
 #if 0
-  /* We explicitly draw dropdown buttons in HTML content 1px bigger up, right,
-   * and bottom so that they overlap the dropdown's border like they're
-   * supposed to.
-   */
-  if (aWidgetType == NS_THEME_MENULIST_BUTTON &&
-      IsHTMLContent(aFrame) &&
-      !IsWidgetStyled(aFrame->GetParent()->PresContext(),
-                      aFrame->GetParent(),
-                      NS_THEME_MENULIST))
-  {
-    int32_t p2a = aContext->AppUnitsPerDevPixel();
-    /* Note: no overflow on the left */
-    nsMargin m(p2a, p2a, p2a, 0);
-    aOverflowRect->Inflate (m);
-    return true;
+  if (IsVistaOrLater()) {
+    /* We explicitly draw dropdown buttons in HTML content 1px bigger
+     * up, right, and bottom so that they overlap the dropdown's border
+     * like they're supposed to.
+     */
+    if (aWidgetType == NS_THEME_MENULIST_BUTTON &&
+        IsHTMLContent(aFrame) &&
+        !IsWidgetStyled(aFrame->GetParent()->PresContext(),
+                        aFrame->GetParent(),
+                        NS_THEME_MENULIST))
+    {
+      int32_t p2a = aContext->AppUnitsPerDevPixel();
+      /* Note: no overflow on the left */
+      nsMargin m(p2a, p2a, p2a, 0);
+      aOverflowRect->Inflate (m);
+      return true;
+    }
   }
 #endif
 
@@ -2199,18 +2384,22 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
     case NS_THEME_SCALETHUMB_VERTICAL:
     {
       *aIsOverridable = false;
-      // On Vista, GetThemePartAndState returns odd values for
+      // on Vista, GetThemePartAndState returns odd values for
       // scale thumbs, so use a hardcoded size instead.
-      if (aWidgetType == NS_THEME_SCALETHUMB_HORIZONTAL ||
-          (aWidgetType == NS_THEME_RANGE_THUMB && IsRangeHorizontal(aFrame))) {
-        aResult->width = 12;
-        aResult->height = 20;
-      } else {
-        aResult->width = 20;
-        aResult->height = 12;
+      if (IsVistaOrLater()) {
+        if (aWidgetType == NS_THEME_SCALETHUMB_HORIZONTAL ||
+            (aWidgetType == NS_THEME_RANGE_THUMB && IsRangeHorizontal(aFrame))) {
+          aResult->width = 12;
+          aResult->height = 20;
+        }
+        else {
+          aResult->width = 20;
+          aResult->height = 12;
+        }
+        ScaleForFrameDPI(aResult, aFrame);
+        return rv;
       }
-      ScaleForFrameDPI(aResult, aFrame);
-      return rv;
+      break;
     }
 
     case NS_THEME_SCROLLBAR:
@@ -2249,6 +2438,11 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
       // stores that info in nsUXThemeData.
       aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx;
       aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy;
+      // For XP, subtract 4 from system metrics dimensions.
+      if (!IsVistaOrLater()) {
+        aResult->width -= 4;
+        aResult->height -= 4;
+      }
       AddPaddingRect(aResult, CAPTIONBUTTON_RESTORE);
       *aIsOverridable = false;
       return rv;
@@ -2256,6 +2450,10 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
     case NS_THEME_WINDOW_BUTTON_MINIMIZE:
       aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx;
       aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy;
+      if (!IsVistaOrLater()) {
+        aResult->width -= 4;
+        aResult->height -= 4;
+      }
       AddPaddingRect(aResult, CAPTIONBUTTON_MINIMIZE);
       *aIsOverridable = false;
       return rv;
@@ -2263,6 +2461,10 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
     case NS_THEME_WINDOW_BUTTON_CLOSE:
       aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx;
       aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy;
+      if (!IsVistaOrLater()) {
+        aResult->width -= 4;
+        aResult->height -= 4;
+      }
       AddPaddingRect(aResult, CAPTIONBUTTON_CLOSE);
       *aIsOverridable = false;
       return rv;
@@ -2392,9 +2594,18 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
     return NS_OK;
   }
 
+  // On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
+  if (!IsVistaOrLater() &&
+      (aWidgetType == NS_THEME_SCROLLBAR_VERTICAL || 
+      aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL)) {
+    *aShouldRepaint = false;
+    return NS_OK;
+  }
+
   // We need to repaint the dropdown arrow in vista HTML combobox controls when
   // the control is closed to get rid of the hover effect.
-  if ((aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON) &&
+  if (IsVistaOrLater() &&
+      (aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON) &&
       IsHTMLContent(aFrame))
   {
     *aShouldRepaint = true;
diff --git a/widget/windows/nsNativeThemeWin.h b/widget/windows/nsNativeThemeWin.h
index 32b82b1e1..f20649444 100644
--- a/widget/windows/nsNativeThemeWin.h
+++ b/widget/windows/nsNativeThemeWin.h
@@ -117,7 +117,8 @@ protected:
   void DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
                                HANDLE aTheme, HDC aHdc,
                                int aPart, int aState,
-                               RECT* aWidgetRect, RECT* aClipRect);
+                               RECT* aWidgetRect, RECT* aClipRect,
+                               gfxFloat aAppUnits);
 
 private:
   TimeStamp mProgressDeterminateTimeStamp;
diff --git a/widget/windows/nsUXThemeConstants.h b/widget/windows/nsUXThemeConstants.h
index ba7afde82..731dcedf2 100644
--- a/widget/windows/nsUXThemeConstants.h
+++ b/widget/windows/nsUXThemeConstants.h
@@ -67,7 +67,7 @@
 #define SP_GRIPPERHOR      8
 #define SP_GRIPPERVERT     9
 
-// Implicit hover state.
+// Vista only; implict hover state.
 // BASE + 0 = UP, + 1 = DOWN, etc.
 #define SP_BUTTON_IMPLICIT_HOVER_BASE   17
 
diff --git a/widget/windows/nsUXThemeData.cpp b/widget/windows/nsUXThemeData.cpp
index 4d9ac9570..bcbd32484 100644
--- a/widget/windows/nsUXThemeData.cpp
+++ b/widget/windows/nsUXThemeData.cpp
@@ -143,8 +143,10 @@ nsUXThemeData::InitTitlebarInfo()
   sCommandButtons[3].cx = sCommandButtons[0].cx * 3;
   sCommandButtons[3].cy = sCommandButtons[0].cy;
 
-  // Trigger a refresh on the next layout.
-  sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = false;
+  // Use system metrics for pre-vista, otherwise trigger a
+  // refresh on the next layout.
+  sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed =
+    !IsVistaOrLater();
 }
 
 // static
@@ -304,7 +306,7 @@ void
 nsUXThemeData::UpdateNativeThemeInfo()
 {
   // Trigger a refresh of themed button metrics if needed
-  sTitlebarInfoPopulatedThemed = false;
+  sTitlebarInfoPopulatedThemed = !IsVistaOrLater();
 
   sIsDefaultWindowsTheme = false;
   sThemeId = LookAndFeel::eWindowsTheme_Generic;
diff --git a/widget/windows/nsWinGesture.h b/widget/windows/nsWinGesture.h
index fdd1588b6..24c1f6b2d 100644
--- a/widget/windows/nsWinGesture.h
+++ b/widget/windows/nsWinGesture.h
@@ -17,6 +17,155 @@
 #include "mozilla/EventForwards.h"
 #include "mozilla/TouchEvents.h"
 
+// Desktop builds target apis for 502. Win8 Metro builds target 602.
+#if WINVER < 0x0602
+
+DECLARE_HANDLE(HGESTUREINFO);
+
+/*
+ * Gesture flags - GESTUREINFO.dwFlags
+ */
+#define GF_BEGIN                        0x00000001
+#define GF_INERTIA                      0x00000002
+#define GF_END                          0x00000004
+
+/*
+ * Gesture configuration structure
+ *   - Used in SetGestureConfig and GetGestureConfig
+ *   - Note that any setting not included in either GESTURECONFIG.dwWant or
+ *     GESTURECONFIG.dwBlock will use the parent window's preferences or
+ *     system defaults.
+ */
+typedef struct tagGESTURECONFIG {
+    DWORD dwID;                     // gesture ID
+    DWORD dwWant;                   // settings related to gesture ID that are to be turned on
+    DWORD dwBlock;                  // settings related to gesture ID that are to be turned off
+} GESTURECONFIG, *PGESTURECONFIG;
+
+/*
+ * Gesture information structure
+ *   - Pass the HGESTUREINFO received in the WM_GESTURE message lParam into the
+ *     GetGestureInfo function to retrieve this information.
+ *   - If cbExtraArgs is non-zero, pass the HGESTUREINFO received in the WM_GESTURE
+ *     message lParam into the GetGestureExtraArgs function to retrieve extended
+ *     argument information.
+ */
+typedef struct tagGESTUREINFO {
+    UINT cbSize;                    // size, in bytes, of this structure (including variable length Args field)
+    DWORD dwFlags;                  // see GF_* flags
+    DWORD dwID;                     // gesture ID, see GID_* defines
+    HWND hwndTarget;                // handle to window targeted by this gesture
+    POINTS ptsLocation;             // current location of this gesture
+    DWORD dwInstanceID;             // internally used
+    DWORD dwSequenceID;             // internally used
+    ULONGLONG ullArguments;         // arguments for gestures whose arguments fit in 8 BYTES
+    UINT cbExtraArgs;               // size, in bytes, of extra arguments, if any, that accompany this gesture
+} GESTUREINFO, *PGESTUREINFO;
+typedef GESTUREINFO const * PCGESTUREINFO;
+
+/*
+ * Gesture notification structure
+ *   - The WM_GESTURENOTIFY message lParam contains a pointer to this structure.
+ *   - The WM_GESTURENOTIFY message notifies a window that gesture recognition is
+ *     in progress and a gesture will be generated if one is recognized under the
+ *     current gesture settings.
+ */
+typedef struct tagGESTURENOTIFYSTRUCT {
+    UINT cbSize;                    // size, in bytes, of this structure
+    DWORD dwFlags;                  // unused
+    HWND hwndTarget;                // handle to window targeted by the gesture
+    POINTS ptsLocation;             // starting location
+    DWORD dwInstanceID;             // internally used
+} GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT;
+
+
+/*
+ * Gesture argument helpers
+ *   - Angle should be a double in the range of -2pi to +2pi
+ *   - Argument should be an unsigned 16-bit value
+ */
+#define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_)     ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0))
+#define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_)   ((((double)(_arg_) / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265)
+
+/*
+ * Gesture configuration flags
+ */
+#define GC_ALLGESTURES                              0x00000001
+
+#define GC_ZOOM                                     0x00000001
+
+#define GC_PAN                                      0x00000001
+#define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY        0x00000002
+#define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY      0x00000004
+#define GC_PAN_WITH_GUTTER                          0x00000008
+#define GC_PAN_WITH_INERTIA                         0x00000010
+
+#define GC_ROTATE                                   0x00000001
+
+#define GC_TWOFINGERTAP                             0x00000001
+
+#define GC_PRESSANDTAP                              0x00000001
+
+/*
+ * Gesture IDs
+ */
+#define GID_BEGIN                       1
+#define GID_END                         2
+#define GID_ZOOM                        3
+#define GID_PAN                         4
+#define GID_ROTATE                      5
+#define GID_TWOFINGERTAP                6
+#define GID_PRESSANDTAP                 7
+
+// Maximum number of gestures that can be included
+// in a single call to SetGestureConfig / GetGestureConfig
+#define GESTURECONFIGMAXCOUNT           256
+
+// If specified, GetGestureConfig returns consolidated configuration
+// for the specified window and it's parent window chain
+#define GCF_INCLUDE_ANCESTORS           0x00000001
+
+// Window events we need to respond to or receive
+#define WM_GESTURE                         0x0119
+#define WM_GESTURENOTIFY                   0x011A
+
+typedef struct _TOUCHINPUT {
+  LONG      x;
+  LONG      y;
+  HANDLE    hSource;
+  DWORD     dwID;
+  DWORD     dwFlags;
+  DWORD     dwMask;
+  DWORD     dwTime;
+  ULONG_PTR dwExtraInfo;
+  DWORD     cxContact;
+  DWORD     cyContact;
+} TOUCHINPUT, *PTOUCHINPUT;
+
+typedef HANDLE HTOUCHINPUT;
+
+#define WM_TOUCH 0x0240
+
+#define TOUCHEVENTF_MOVE       0x0001
+#define TOUCHEVENTF_DOWN       0x0002
+#define TOUCHEVENTF_UP         0x0004
+#define TOUCHEVENTF_INRANGE    0x0008
+#define TOUCHEVENTF_PRIMARY    0x0010
+#define TOUCHEVENTF_NOCOALESCE 0x0020
+#define TOUCHEVENTF_PEN        0x0040
+#define TOUCHEVENTF_PALM       0x0080
+
+#define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
+#define TOUCHINPUTMASKF_EXTRAINFO      0x0002
+#define TOUCHINPUTMASKF_CONTACTAREA    0x0004
+
+#define TOUCH_COORD_TO_PIXEL(C) (C/100)
+
+#define TWF_FINETOUCH          0x0001
+#define TWF_WANTPALM           0x0002
+
+#endif // WINVER < 0x0602
+
 // WM_TABLET_QUERYSYSTEMGESTURESTATUS return values
 #define TABLET_ROTATE_GESTURE_ENABLE    0x02000000
 
@@ -56,7 +205,7 @@ public:
   bool GetTouchInputInfo(HTOUCHINPUT hTouchInput, uint32_t cInputs, PTOUCHINPUT pInputs);
   bool CloseTouchInputHandle(HTOUCHINPUT hTouchInput);
   bool IsAvailable();
-
+  
   // Simple gesture process
   bool ProcessGestureMessage(HWND hWnd, WPARAM wParam, LPARAM lParam, mozilla::WidgetSimpleGestureEvent& evt);
 
@@ -67,7 +216,7 @@ public:
   void UpdatePanFeedbackX(HWND hWnd, int32_t scrollOverflow, bool& endFeedback);
   void UpdatePanFeedbackY(HWND hWnd, int32_t scrollOverflow, bool& endFeedback);
   void PanFeedbackFinalize(HWND hWnd, bool endFeedback);
-
+  
 public:
   // Helpers
   bool GetGestureInfo(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo);
@@ -135,3 +284,5 @@ private:
 };
 
 #endif /* WinGesture_h__ */
+
+
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
index b2bb59bd3..a8923f78e 100644
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -266,7 +266,8 @@ LONG            nsWindow::sLastMouseDownTime      = 0L;
 LONG            nsWindow::sLastClickCount         = 0L;
 BYTE            nsWindow::sLastMouseButton        = 0;
 
-bool            nsWindow::sHaveInitializedPrefs   = false;
+// Trim heap on minimize. (initialized, but still true.)
+int             nsWindow::sTrimOnMinimize         = 2;
 
 TriStateBool nsWindow::sHasBogusPopupsDropShadowOnMultiMonitor = TRI_UNKNOWN;
 
@@ -782,7 +783,7 @@ nsWindow::Create(nsIWidget* aParent,
       parent = nullptr;
     }
 
-    if (!IsWin8OrLater() &&
+    if (IsVistaOrLater() && !IsWin8OrLater() &&
         HasBogusPopupsDropShadowOnMultiMonitor()) {
       extendedStyle |= WS_EX_COMPOSITED;
     }
@@ -907,13 +908,20 @@ nsWindow::Create(nsIWidget* aParent,
   mDefaultIMC.Init(this);
   IMEHandler::InitInputContext(this, mInputContext);
 
-  // Do some initialization work, but only if (a) it hasn't already been done,
-  // and (b) this is the hidden window (which is conveniently created before
-  // any visible windows but after the profile has been initialized).
-  if (!sHaveInitializedPrefs && mWindowType == eWindowType_invisible) {
+  // If the internal variable set by the config.trim_on_minimize pref has not
+  // been initialized, and if this is the hidden window (conveniently created
+  // before any visible windows, and after the profile has been initialized),
+  // do some initialization work.
+  if (sTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) {
+    // Our internal trim prevention logic is effective on 2K/XP at maintaining
+    // the working set when windows are minimized, but on Vista and up it has
+    // little to no effect. Since this feature has been the source of numerous
+    // bugs over the years, disable it (sTrimOnMinimize=1) on Vista and up.
+    sTrimOnMinimize =
+      Preferences::GetBool("config.trim_on_minimize",
+        IsVistaOrLater() ? 1 : 0);
     sSwitchKeyboardLayout =
       Preferences::GetBool("intl.keyboard.per_window_layout", false);
-    sHaveInitializedPrefs = true;
   }
 
   // Query for command button metric data for rendering the titlebar. We
@@ -1639,10 +1647,9 @@ bool nsWindow::IsVisible() const
 
 // XP and Vista visual styles sometimes require window clipping regions to be applied for proper
 // transparency. These routines are called on size and move operations.
-// XXX this is apparently still needed in Windows 7 and later
 void nsWindow::ClearThemeRegion()
 {
-  if (!HasGlass() &&
+  if (IsVistaOrLater() && !HasGlass() &&
       (mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
        (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
     SetWindowRgn(mWnd, nullptr, false);
@@ -1656,7 +1663,7 @@ void nsWindow::SetThemeRegion()
   // so default constants are used for part and state. At some point we might need part and
   // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
   // change shape based on state haven't come up.
-  if (!HasGlass() &&
+  if (IsVistaOrLater() && !HasGlass() &&
       (mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
        (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
     HRGN hRgn = nullptr;
@@ -2073,7 +2080,13 @@ nsWindow::SetSizeMode(nsSizeMode aMode)
         break;
 
       case nsSizeMode_Minimized :
-        mode = SW_MINIMIZE;
+        // Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
+        // keeps the window active in the tray. So after the window is minimized,
+        // windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
+        // we will do some additional processing to get the active window set right.
+        // If sTrimOnMinimize is set, we let windows handle minimization normally
+        // using SW_MINIMIZE.
+        mode = sTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
         break;
 
       default :
@@ -5815,6 +5828,12 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
     case WM_SYSCOMMAND:
     {
       WPARAM filteredWParam = (wParam &0xFFF0);
+      // prevent Windows from trimming the working set. bug 76831
+      if (!sTrimOnMinimize && filteredWParam == SC_MINIMIZE) {
+        ::ShowWindow(mWnd, SW_SHOWMINIMIZED);
+        result = true;
+      }
+
       if (mSizeMode == nsSizeMode_Fullscreen &&
           filteredWParam == SC_RESTORE &&
           GetCurrentShowCmd(mWnd) != SW_SHOWMINIMIZED) {
@@ -6432,6 +6451,14 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
     else
       mSizeMode = nsSizeMode_Normal;
 
+    // If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
+    // SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
+    // prevents the working set from being trimmed but keeps the window active.
+    // After the window is minimized, we need to do some touch up work on the
+    // active window. (bugs 76831 & 499816)
+    if (!sTrimOnMinimize && nsSizeMode_Minimized == mSizeMode)
+      ActivateOtherWindowHelper(mWnd);
+
 #ifdef WINSTATE_DEBUG_OUTPUT
     switch (mSizeMode) {
       case nsSizeMode_Normal:
@@ -6552,6 +6579,31 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
   }
 }
 
+// static
+void nsWindow::ActivateOtherWindowHelper(HWND aWnd)
+{
+  // Find the next window that is enabled, visible, and not minimized.
+  HWND hwndBelow = ::GetNextWindow(aWnd, GW_HWNDNEXT);
+  while (hwndBelow && (!::IsWindowEnabled(hwndBelow) || !::IsWindowVisible(hwndBelow) ||
+                       ::IsIconic(hwndBelow))) {
+    hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
+  }
+
+  // Push ourselves to the bottom of the stack, then activate the
+  // next window.
+  ::SetWindowPos(aWnd, HWND_BOTTOM, 0, 0, 0, 0,
+                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+  if (hwndBelow)
+    ::SetForegroundWindow(hwndBelow);
+
+  // Play the minimize sound while we're here, since that is also
+  // forgotten when we use SW_SHOWMINIMIZED.
+  nsCOMPtr<nsISound> sound(do_CreateInstance("@mozilla.org/sound;1"));
+  if (sound) {
+    sound->PlaySystemSound(NS_LITERAL_STRING("Minimize"));
+  }
+}
+
 void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
 {
   // Update non-client margins if the frame size is changing, and let the
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h
index 199500e9c..248978bd7 100644
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -486,6 +486,7 @@ protected:
                                               bool aIntersectWithExisting) override;
   nsIntRegion             GetRegionToPaint(bool aForceFullRepaint,
                                            PAINTSTRUCT ps, HDC aDC);
+  static void             ActivateOtherWindowHelper(HWND aWnd);
   void                    ClearCachedResources();
   nsIWidgetListener*      GetPaintListener();
 
@@ -551,7 +552,7 @@ protected:
   static bool           sJustGotDeactivate;
   static bool           sJustGotActivate;
   static bool           sIsInMouseCapture;
-  static bool           sHaveInitializedPrefs;
+  static int            sTrimOnMinimize;
 
   // Always use the helper method to read this property.  See bug 603793.
   static TriStateBool   sHasBogusPopupsDropShadowOnMultiMonitor;
diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp
index 6ead5cdc7..c72ea48d7 100644
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -111,6 +111,7 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**);
 #include "SpecialSystemDirectory.h"
 
 #if defined(XP_WIN)
+#include "mozilla/WindowsVersion.h"
 #include "nsWindowsRegKey.h"
 #endif
 
@@ -583,6 +584,8 @@ NS_InitXPCOM2(nsIServiceManager** aResult,
 
   NS_StartupLocalFile();
 
+  StartupSpecialSystemDirectory();
+
   nsDirectoryService::RealInit();
 
   bool value;
diff --git a/xpcom/glue/nsThreadUtils.cpp b/xpcom/glue/nsThreadUtils.cpp
index 2f2383fd8..287ada7be 100644
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -20,10 +20,15 @@
 
 #ifdef XP_WIN
 #include <windows.h>
+#include "mozilla/WindowsVersion.h"
+using mozilla::IsVistaOrLater;
 #elif defined(XP_MACOSX)
 #include <sys/resource.h>
 #endif
 
+#include <pratom.h>
+#include <prthread.h>
+
 using namespace mozilla;
 
 #ifndef XPCOM_GLUE_AVOID_NSPR
@@ -438,7 +443,8 @@ nsThreadPoolNaming::SetThreadPoolName(const nsACString& aPoolName,
 nsAutoLowPriorityIO::nsAutoLowPriorityIO()
 {
 #if defined(XP_WIN)
-  lowIOPrioritySet = SetThreadPriority(GetCurrentThread(),
+  lowIOPrioritySet = IsVistaOrLater() &&
+                     SetThreadPriority(GetCurrentThread(),
                                        THREAD_MODE_BACKGROUND_BEGIN);
 #elif defined(XP_MACOSX)
   oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);
diff --git a/xpcom/io/SpecialSystemDirectory.cpp b/xpcom/io/SpecialSystemDirectory.cpp
index ab65d38f9..9ce8eb85b 100644
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -12,6 +12,7 @@
 #if defined(XP_WIN)
 
 #include <windows.h>
+#include <shlobj.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -19,6 +20,9 @@
 #include <shlobj.h>
 #include <knownfolders.h>
 #include <guiddef.h>
+#include "mozilla/WindowsVersion.h"
+
+using mozilla::IsWin7OrLater;
 
 #elif defined(XP_UNIX)
 
@@ -47,17 +51,40 @@
 #endif
 #endif
 
+#ifdef XP_WIN
+typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
+                                               DWORD dwFlags,
+                                               HANDLE hToken,
+                                               PWSTR* ppszPath);
+
+static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
+#endif
+
+void
+StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+  // SHGetKnownFolderPath is only available on Windows Vista
+  // so that we need to use GetProcAddress to get the pointer.
+  HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
+  if (hShell32DLLInst) {
+    gGetKnownFolderPath = (nsGetKnownFolderPath)
+      GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
+  }
+#endif
+}
+
 #if defined (XP_WIN)
 
 static nsresult
 GetKnownFolder(GUID* aGuid, nsIFile** aFile)
 {
-  if (!aGuid) {
+  if (!aGuid || !gGetKnownFolderPath) {
     return NS_ERROR_FAILURE;
   }
 
   PWSTR path = nullptr;
-  SHGetKnownFolderPath(*aGuid, 0, nullptr, &path);
+  gGetKnownFolderPath(*aGuid, 0, nullptr, &path);
 
   if (!path) {
     return NS_ERROR_FAILURE;
@@ -112,13 +139,19 @@ SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
 }
 
 /*
- * Return the default save-to location for the Windows Library passed in
- * through aFolderId.
+ * Check to see if we're on Win7 and up, and if so, returns the default
+ * save-to location for the Windows Library passed in through aFolderId.
+ * Otherwise falls back on pre-win7 GetWindowsFolder.
  */
 static nsresult
 GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
                      nsIFile** aFile)
 {
+  // Skip off checking for library support if the os is Vista or lower.
+  if (!IsWin7OrLater()) {
+    return GetWindowsFolder(aFallbackFolderId, aFile);
+  }
+
   RefPtr<IShellLibrary> shellLib;
   RefPtr<IShellItem> savePath;
   HRESULT hr =
@@ -707,6 +740,8 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
     }
 #if defined(MOZ_CONTENT_SANDBOX)
     case Win_LocalAppdataLow: {
+      // This should only really fail on versions pre-Vista, in which case this
+      // shouldn't have been used in the first place.
       GUID localAppDataLowGuid = FOLDERID_LocalAppDataLow;
       return GetKnownFolder(&localAppDataLowGuid, aFile);
     }
diff --git a/xpcom/io/SpecialSystemDirectory.h b/xpcom/io/SpecialSystemDirectory.h
index 7c7f8fa42..dd3d88379 100644
--- a/xpcom/io/SpecialSystemDirectory.h
+++ b/xpcom/io/SpecialSystemDirectory.h
@@ -16,6 +16,9 @@
 #include "prenv.h"
 #endif
 
+extern void StartupSpecialSystemDirectory();
+
+
 enum SystemDirectories {
   OS_DriveDirectory         =   1,
   OS_TemporaryDirectory     =   2,
diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp
index 66e267807..3a7e570f5 100644
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -7,6 +7,7 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/UniquePtrExtensions.h"
+#include "mozilla/WindowsVersion.h"
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
@@ -1969,11 +1970,13 @@ nsLocalFile::CopySingleFile(nsIFile* aSourceFile, nsIFile* aDestParent,
   // So we only use COPY_FILE_NO_BUFFERING when we have a remote drive.
   int copyOK;
   DWORD dwCopyFlags = COPY_FILE_ALLOW_DECRYPTED_DESTINATION;
-  bool path1Remote, path2Remote;
-  if (!IsRemoteFilePath(filePath.get(), path1Remote) ||
-      !IsRemoteFilePath(destPath.get(), path2Remote) ||
-      path1Remote || path2Remote) {
-    dwCopyFlags |= COPY_FILE_NO_BUFFERING;
+  if (IsVistaOrLater()) {
+    bool path1Remote, path2Remote;
+    if (!IsRemoteFilePath(filePath.get(), path1Remote) ||
+        !IsRemoteFilePath(destPath.get(), path2Remote) ||
+        path1Remote || path2Remote) {
+      dwCopyFlags |= COPY_FILE_NO_BUFFERING;
+    }
   }
 
   if (!move) {
