Backout f1acc52a59da (bug 719983) & 6771bd53e267 (bug 699247) for 30% WinXp Ts regression
authorEd Morley <bmo@edmorley.co.uk>
Wed, 08 Feb 2012 21:04:21 +0000
changeset 89731 07da69ba7e5213506e2e5d8168235c0b66d9107d
parent 89730 8df98bb171f046ef16d3ff4b61416a12d965254c
child 89732 094e4a9472a1d1bba36cd5b7533f6cc929ab93c9
push idunknown
push userunknown
push dateunknown
bugs719983, 699247
milestone13.0a1
backs outf1acc52a59da19db0f623dce6fe6c3fd71b6a84c
Backout f1acc52a59da (bug 719983) & 6771bd53e267 (bug 699247) for 30% WinXp Ts regression
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsPluginsDirWin.cpp
dom/plugins/ipc/PluginProcessChild.cpp
extensions/auth/nsAuthSSPI.cpp
gfx/thebes/gfxDWriteFonts.cpp
gfx/thebes/gfxGDIFontList.cpp
gfx/thebes/gfxWindowsPlatform.h
hal/windows/WindowsBattery.cpp
ipc/app/MozillaRuntimeMain.cpp
netwerk/base/src/nsAutodialWin.cpp
netwerk/base/src/nsAutodialWin.h
netwerk/base/src/nsSocketTransportService2.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/system/win32/nsNotifyAddrListener.cpp
netwerk/system/win32/nsNotifyAddrListener.h
toolkit/library/Makefile.in
toolkit/xre/nsWindowsWMain.cpp
uriloader/exthandler/win/nsMIMEInfoWin.cpp
widget/windows/GfxInfo.cpp
widget/windows/WinUtils.h
widget/windows/nsLookAndFeel.cpp
widget/windows/nsNativeThemeWin.cpp
widget/windows/nsUXThemeConstants.h
widget/windows/nsUXThemeData.cpp
widget/windows/nsUXThemeData.h
widget/windows/nsWindow.cpp
widget/windows/nsWindowGfx.cpp
widget/windows/nsWindowGfx.h
widget/xpwidgets/GfxDriverInfo.h
widget/xpwidgets/GfxInfoBase.cpp
xpcom/base/nsSetDllDirectory.h
xpcom/base/nsStackWalk.cpp
xpcom/io/SpecialSystemDirectory.cpp
xpcom/io/nsLocalFileWin.cpp
xpcom/io/nsLocalFileWin.h
xpcom/threads/nsProcess.h
xpcom/threads/nsProcessCommon.cpp
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -348,16 +348,26 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
       }
       if (versionPrefix.EqualsASCII("10.1") && GMA9XXGraphics()) {
         return false;
       }
     }
   }
 #endif
 
+#ifdef XP_WIN
+  OSVERSIONINFO osVerInfo = {0};
+  osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
+  GetVersionEx(&osVerInfo);
+  // Always disabled on 2K or less. (bug 536303)
+  if (osVerInfo.dwMajorVersion < 5 ||
+      (osVerInfo.dwMajorVersion == 5 && osVerInfo.dwMinorVersion == 0))
+    return false;
+#endif
+
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (!prefs) {
     return false;
   }
 
   // Get per-library whitelist/blacklist pref string
   // "dom.ipc.plugins.enabled.filename.dll" and fall back to the default value
   // of "dom.ipc.plugins.enabled"
--- a/dom/plugins/base/nsPluginsDirWin.cpp
+++ b/dom/plugins/base/nsPluginsDirWin.cpp
@@ -52,16 +52,17 @@
 #include "prprf.h"
 
 #include "windows.h"
 #include "winbase.h"
 
 #include "nsString.h"
 #include "nsILocalFile.h"
 #include "nsUnicharUtils.h"
+#include "nsSetDllDirectory.h"
 
 using namespace mozilla;
 
 /* Local helper functions */
 
 static char* GetKeyValue(void* verbuf, const WCHAR* key,
                          UINT language, UINT codepage)
 {
@@ -297,25 +298,25 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
   NS_ASSERTION(dwCheck <= MAX_PATH + 1, "Error in Loading plugin");
 
   if (dwCheck <= MAX_PATH + 1) {
     restoreOrigDir = SetCurrentDirectoryW(pluginFolderPath.get());
     NS_ASSERTION(restoreOrigDir, "Error in Loading plugin");
   }
 
   if (protectCurrentDirectory) {
-    SetDllDirectory(NULL);
+    mozilla::NS_SetDllDirectory(NULL);
   }
 
   nsresult rv = plugin->Load(outLibrary);
   if (NS_FAILED(rv))
       *outLibrary = NULL;
 
   if (protectCurrentDirectory) {
-    SetDllDirectory(L"");
+    mozilla::NS_SetDllDirectory(L"");
   }
 
   if (restoreOrigDir) {
     BOOL bCheck = SetCurrentDirectoryW(aOrigDir);
     NS_ASSERTION(bCheck, "Error in Loading plugin");
   }
 
   return rv;
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -142,17 +142,17 @@ PluginProcessChild::Init()
     const std::string shockwaveDirectorPluginFilename("\\np32dsw.dll");
     std::size_t index = caseInsensitiveFind(pluginFilename, shockwaveDirectorPluginFilename);
     if (index != std::string::npos &&
         index + shockwaveDirectorPluginFilename.length() == pluginFilename.length()) {
         protectCurrentDirectory = false;
     }
     if (protectCurrentDirectory) {
         SanitizeEnvironmentVariables();
-        SetDllDirectory(L"");
+        NS_SetDllDirectory(L"");
     }
 
 #else
 #  error Sorry
 #endif
 
     if (NS_FAILED(nsRegion::InitStatic())) {
       NS_ERROR("Could not initialize nsRegion");
--- a/extensions/auth/nsAuthSSPI.cpp
+++ b/extensions/auth/nsAuthSSPI.cpp
@@ -102,24 +102,43 @@ static const char *MapErrorCode(int rc)
     return "<unknown>";
 }
 #else
 #define MapErrorCode(_rc) ""
 #endif
 
 //-----------------------------------------------------------------------------
 
+static HINSTANCE                 sspi_lib; 
 static PSecurityFunctionTableW   sspi;
 
 static nsresult
 InitSSPI()
 {
+    PSecurityFunctionTableW (*initFun)(void);
+
     LOG(("  InitSSPI\n"));
 
-    sspi = InitSecurityInterfaceW();
+    sspi_lib = LoadLibraryW(L"secur32.dll");
+    if (!sspi_lib) {
+        sspi_lib = LoadLibraryW(L"security.dll");
+        if (!sspi_lib) {
+            LOG(("SSPI library not found"));
+            return NS_ERROR_UNEXPECTED;
+        }
+    }
+
+    initFun = (PSecurityFunctionTableW (*)(void))
+            GetProcAddress(sspi_lib, "InitSecurityInterfaceW");
+    if (!initFun) {
+        LOG(("InitSecurityInterfaceW not found"));
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    sspi = initFun();
     if (!sspi) {
         LOG(("InitSecurityInterfaceW failed"));
         return NS_ERROR_UNEXPECTED;
     }
 
     return NS_OK;
 }
 
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -77,22 +77,38 @@ GetCairoAntialiasOption(gfxFont::Antiali
 #ifndef SPI_GETFONTSMOOTHINGTYPE
 #define SPI_GETFONTSMOOTHINGTYPE 0x200a
 #endif
 #ifndef FE_FONTSMOOTHINGCLEARTYPE
 #define FE_FONTSMOOTHINGCLEARTYPE 2
 #endif
 
 static bool
+HasClearType()
+{
+    OSVERSIONINFO versionInfo;
+    versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    return (GetVersionEx(&versionInfo) &&
+            (versionInfo.dwMajorVersion > 5 ||
+             (versionInfo.dwMajorVersion == 5 &&
+              versionInfo.dwMinorVersion >= 1))); // XP or newer
+}
+
+static bool
 UsingClearType()
 {
     BOOL fontSmoothing;
     if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0) ||
         !fontSmoothing)
     {
+        return false;    
+    }
+
+    if (!HasClearType()) {
         return false;
     }
 
     UINT type;
     if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &type, 0) &&
         type == FE_FONTSMOOTHINGCLEARTYPE)
     {
         return true;
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -60,17 +60,16 @@
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIWindowsRegKey.h"
 
 #include "mozilla/Telemetry.h"
 
 #include <usp10.h>
-#include <t2embapi.h>
 
 using namespace mozilla;
 
 #define ROUND(x) floor((x) + 0.5)
 
 
 #ifndef CLEARTYPE_QUALITY
 #define CLEARTYPE_QUALITY 5
@@ -98,28 +97,72 @@ BuildKeyNameFromFontName(nsAString &aNam
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
     ToLowerCase(aName);
 }
 
 // Implementation of gfxPlatformFontList for Win32 GDI,
 // using GDI font enumeration APIs to get the list of fonts
 
+// from t2embapi.h, included in Platform SDK 6.1 but not 6.0
+
+#ifndef __t2embapi__
+
+#define TTLOAD_PRIVATE                  0x00000001
+#define LICENSE_PREVIEWPRINT            0x0004
+#define E_NONE                          0x0000L
+
+typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
+
+typedef struct
+{
+    unsigned short usStructSize;    // size in bytes of structure client should set to sizeof(TTLOADINFO)
+    unsigned short usRefStrSize;    // size in wide characters of pusRefStr including NULL terminator
+    unsigned short *pusRefStr;      // reference or actual string.
+}TTLOADINFO;
+
+LONG WINAPI TTLoadEmbeddedFont
+(
+    HANDLE*  phFontReference,           // on completion, contains handle to identify embedded font installed
+                                        // on system
+    ULONG    ulFlags,                   // flags specifying the request 
+    ULONG*   pulPrivStatus,             // on completion, contains the embedding status
+    ULONG    ulPrivs,                   // allows for the reduction of licensing privileges
+    ULONG*   pulStatus,                 // on completion, may contain status flags for request 
+    READEMBEDPROC lpfnReadFromStream,   // callback function for doc/disk reads
+    LPVOID   lpvReadStream,             // the input stream tokin
+    LPWSTR   szWinFamilyName,           // the new 16 bit windows family name can be NULL
+    LPSTR    szMacFamilyName,           // the new 8 bit mac family name can be NULL
+    TTLOADINFO* pTTLoadInfo             // optional security
+);
+
+#endif // __t2embapi__
+
+typedef LONG( WINAPI *TTLoadEmbeddedFontProc ) (HANDLE* phFontReference, ULONG ulFlags, ULONG* pulPrivStatus, ULONG ulPrivs, ULONG* pulStatus, 
+                                             READEMBEDPROC lpfnReadFromStream, LPVOID lpvReadStream, LPWSTR szWinFamilyName, 
+                                             LPSTR szMacFamilyName, TTLOADINFO* pTTLoadInfo);
+
+typedef LONG( WINAPI *TTDeleteEmbeddedFontProc ) (HANDLE hFontReference, ULONG ulFlags, ULONG* pulStatus);
+
+
+static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nsnull;
+static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nsnull;
+
 class WinUserFontData : public gfxUserFontData {
 public:
     WinUserFontData(HANDLE aFontRef, bool aIsEmbedded)
         : mFontRef(aFontRef), mIsEmbedded(aIsEmbedded)
     { }
 
     virtual ~WinUserFontData()
     {
         if (mIsEmbedded) {
             ULONG pulStatus;
             LONG err;
-            err = TTDeleteEmbeddedFont(mFontRef, 0, &pulStatus);
+            err = TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
 #if DEBUG
             if (err != E_NONE) {
                 char buf[256];
                 sprintf(buf, "error deleting embedded font handle (%p) - TTDeleteEmbeddedFont returned %8.8x", mFontRef, err);
                 NS_ASSERTION(err == E_NONE, buf);
             }
 #endif
         } else {
@@ -546,16 +589,18 @@ GDIFontFamily::FindStyleVariations()
  *
  * gfxGDIFontList
  *
  */
 
 gfxGDIFontList::gfxGDIFontList()
 {
     mFontSubstitutes.Init(50);
+
+    InitializeFontEmbeddingProcs();
 }
 
 static void
 RemoveCharsetFromFontSubstitute(nsAString &aName)
 {
     PRInt32 comma = aName.FindChar(PRUnichar(','));
     if (comma >= 0)
         aName.Truncate(comma);
@@ -732,16 +777,25 @@ gfxGDIFontList::LookupLocalFont(const gf
     if (!fe)
         return nsnull;
 
     fe->mIsUserFont = true;
     fe->mIsLocalUserFont = true;
     return fe;
 }
 
+void gfxGDIFontList::InitializeFontEmbeddingProcs()
+{
+    HMODULE fontlib = LoadLibraryW(L"t2embed.dll");
+    if (!fontlib)
+        return;
+    TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc) GetProcAddress(fontlib, "TTLoadEmbeddedFont");
+    TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc) GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
+}
+
 // used to control stream read by Windows TTLoadEmbeddedFont API
 
 class EOTFontStreamReader {
 public:
     EOTFontStreamReader(const PRUint8 *aFontData, PRUint32 aLength, PRUint8 *aEOTHeader, 
                            PRUint32 aEOTHeaderLen, FontDataOverlay *aNameOverlay)
         : mCurrentChunk(0), mChunkOffset(0)
     {
@@ -835,16 +889,20 @@ gfxGDIFontList::MakePlatformFont(const g
     struct FontDataDeleter {
         FontDataDeleter(const PRUint8 *aFontData)
             : mFontData(aFontData) { }
         ~FontDataDeleter() { NS_Free((void*)mFontData); }
         const PRUint8 *mFontData;
     };
     FontDataDeleter autoDelete(aFontData);
 
+    // if calls aren't available, bail
+    if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
+        return nsnull;
+
     bool hasVertical;
     bool isCFF = gfxFontUtils::IsCffFont(aFontData, hasVertical);
 
     nsresult rv;
     HANDLE fontRef = nsnull;
     bool isEmbedded = false;
 
     nsAutoString uniqueName;
@@ -873,21 +931,21 @@ gfxGDIFontList::MakePlatformFont(const g
             eotlen = eotHeader.Length();
             buffer = reinterpret_cast<PRUint8*> (eotHeader.Elements());
             
             PRInt32 ret;
             ULONG privStatus, pulStatus;
             EOTFontStreamReader eotReader(aFontData, aLength, buffer, eotlen,
                                           &overlayNameData);
 
-            ret = TTLoadEmbeddedFont(&fontRef, TTLOAD_PRIVATE, &privStatus,
-                                     LICENSE_PREVIEWPRINT, &pulStatus,
-                                     EOTFontStreamReader::ReadEOTStream,
-                                     &eotReader,
-                                     (PRUnichar*)(fontName.get()), 0, 0);
+            ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
+                                       LICENSE_PREVIEWPRINT, &pulStatus,
+                                       EOTFontStreamReader::ReadEOTStream,
+                                       &eotReader,
+                                       (PRUnichar*)(fontName.get()), 0, 0);
             if (ret != E_NONE) {
                 fontRef = nsnull;
                 char buf[256];
                 sprintf(buf, "font (%s) not loaded using TTLoadEmbeddedFont - error %8.8x", NS_ConvertUTF16toUTF8(aProxyEntry->FamilyName()).get(), ret);
                 NS_WARNING(buf);
             }
         }
     }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -218,16 +218,17 @@ public:
     // if either of these prefs are enabled and apply, use ClearType rendering
     bool UseClearTypeForDownloadableFonts();
     bool UseClearTypeAlways();
 
     // OS version in 16.16 major/minor form
     // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
     enum {
         kWindowsUnknown = 0,
+        kWindows2000 = 0x50000,
         kWindowsXP = 0x50001,
         kWindowsServer2003 = 0x50002,
         kWindowsVista = 0x60000,
         kWindows7 = 0x60001
     };
 
     static PRInt32 WindowsOSVersion(PRInt32 *aBuildNum = nsnull);
 
--- a/hal/windows/WindowsBattery.cpp
+++ b/hal/windows/WindowsBattery.cpp
@@ -160,17 +160,17 @@ EnableBatteryNotifications()
                                         DEVICE_NOTIFY_WINDOW_HANDLE);
     sCapacityHandle =
       sRegisterPowerSettingNotification(sHWnd,
                                         &GUID_BATTERY_PERCENTAGE_REMAINING,
                                         DEVICE_NOTIFY_WINDOW_HANDLE);
   } else
 #endif
   {
-    // for Windows XP.  If we remove Windows XP support,
+    // for Windows 2000 and Windwos 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,
                                          nsnull,
                                          Preferences::GetInt("dom.battery.timer",
                                                              30000 /* 30s */),
                                          nsITimer::TYPE_REPEATING_SLACK);
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -69,17 +69,17 @@ main(int argc, char* argv[])
     GeckoProcessType proctype = XRE_StringToChildProcessType(argv[--argc]);
 
 #ifdef XP_WIN
     // For plugins, this is done in PluginProcessChild::Init, as we need to
     // avoid it for unsupported plugins.  See PluginProcessChild::Init for
     // the details.
     if (proctype != GeckoProcessType_Plugin) {
         mozilla::SanitizeEnvironmentVariables();
-        SetDllDirectory(L"");
+        mozilla::NS_SetDllDirectory(L"");
     }
 #endif
 
     nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
     NS_ENSURE_SUCCESS(rv, 1);
 
     return 0;
 }
--- a/netwerk/base/src/nsAutodialWin.cpp
+++ b/netwerk/base/src/nsAutodialWin.cpp
@@ -74,16 +74,19 @@ static PRLogModuleInfo* gLog = nsnull;
 PRIntervalTime nsAutodial::mDontRetryUntil = 0;
 
 // ctor. 
 nsAutodial::nsAutodial()
 :   mAutodialBehavior(AUTODIAL_DEFAULT),
     mNumRASConnectionEntries(0),
     mAutodialServiceDialingLocation(-1)
 {
+    mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
+    GetVersionEx(&mOSVerInfo);
+
     // Initializations that can be made again since RAS OS settings can 
     // change.
     Init();
 }
 
 // dtor
 nsAutodial::~nsAutodial()
 {
@@ -424,47 +427,72 @@ nsresult nsAutodial::GetDefaultEntryName
         return GetFirstEntryName(entryName, bufferSize);
     }
 
     // Multiple RAS dialup entries. If a default configured in the registry,
     // use it. 
     //
     // For Windows XP: HKCU/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
     //              or HKLM/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
+    // For Windows 2K: HKCU/RemoteAccess/InternetProfile.
 
-    const PRUnichar* key = L"Software\\Microsoft\\RAS Autodial\\Default";
-    const PRUnichar* val = L"DefaultInternet";
+    const PRUnichar* key = nsnull;
+    const PRUnichar* val = nsnull;
 
     HKEY hKey = 0;
     LONG result = 0;
 
-    
-    // Try HKCU first.
-    result = ::RegOpenKeyExW(
-                HKEY_CURRENT_USER, 
-                key, 
-                0, 
-                KEY_READ, 
-                &hKey);
+    // Windows 2000
+    if ((mOSVerInfo.dwMajorVersion == 5) && (mOSVerInfo.dwMinorVersion == 0)) // Windows 2000
+    {
+        key = L"RemoteAccess";
+        val = L"InternetProfile";
 
-    if (result != ERROR_SUCCESS)
-    {
-        // If not present, try HKLM.
         result = ::RegOpenKeyExW(
-                    HKEY_LOCAL_MACHINE, 
+                    HKEY_CURRENT_USER, 
                     key, 
                     0, 
                     KEY_READ, 
                     &hKey);
 
         if (result != ERROR_SUCCESS)
         {
             return NS_ERROR_FAILURE;
         }
     }
+    else  // Windows XP
+    {
+        key = L"Software\\Microsoft\\RAS Autodial\\Default";
+        val = L"DefaultInternet";
+
+        
+        // Try HKCU first.
+        result = ::RegOpenKeyExW(
+                    HKEY_CURRENT_USER, 
+                    key, 
+                    0, 
+                    KEY_READ, 
+                    &hKey);
+
+        if (result != ERROR_SUCCESS)
+        {
+            // If not present, try HKLM.
+            result = ::RegOpenKeyExW(
+                        HKEY_LOCAL_MACHINE, 
+                        key, 
+                        0, 
+                        KEY_READ, 
+                        &hKey);
+
+            if (result != ERROR_SUCCESS)
+            {
+                return NS_ERROR_FAILURE;
+            }
+        }
+    }
 
 
     DWORD entryType = 0;
     DWORD buffSize = bufferSize;
 
     result = ::RegQueryValueExW(hKey, 
                                 val, 
                                 nsnull, 
--- a/netwerk/base/src/nsAutodialWin.h
+++ b/netwerk/base/src/nsAutodialWin.h
@@ -121,16 +121,19 @@ private:
     int mNumRASConnectionEntries;
 
     // Default connection entry name.
     PRUnichar mDefaultEntryName[RAS_MaxEntryName + 1];  
 
     // Don't try to dial again within a few seconds of when user pressed cancel.
     static PRIntervalTime mDontRetryUntil;
 
+    // OS version info.
+    OSVERSIONINFO mOSVerInfo;
+
 public:
   
     // ctor
     nsAutodial();
 
     // dtor
     virtual ~nsAutodial();
 
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -955,16 +955,26 @@ nsSocketTransportService::DiscoverMaxCou
 
     rlimitData.rlim_cur = maxallowed;
     setrlimit(RLIMIT_NOFILE, &rlimitData);
     if (getrlimit(RLIMIT_NOFILE, &rlimitData) != -1)
         if (rlimitData.rlim_cur > SOCKET_LIMIT_MIN + 250)
             gMaxCount = rlimitData.rlim_cur - 250;
 
 #elif defined(XP_WIN) && !defined(WIN_CE)
+    // win 95, 98, etc had a limit of 100 - so we will just
+    // use the historical 50 in every case older than XP (0x501).
     // >= XP is confirmed to have at least 1000
-    gMaxCount = SOCKET_LIMIT_TARGET;
+
+    OSVERSIONINFO osInfo = { sizeof(OSVERSIONINFO) };
+    if (GetVersionEx(&osInfo)) {
+        PRInt32 version = 
+            (osInfo.dwMajorVersion & 0xff) << 8 | 
+            (osInfo.dwMinorVersion & 0xff);
+        if (version >= 0x501)                    /* xp or later */
+            gMaxCount = SOCKET_LIMIT_TARGET;
+    }
 #else
     // other platforms are harder to test - so leave at safe legacy value
 #endif
 
     return PR_SUCCESS;
 }
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -648,16 +648,18 @@ nsHttpHandler::BuildUserAgent()
     // App portion
     mUserAgent += ' ';
     mUserAgent += mAppName;
     mUserAgent += '/';
     mUserAgent += mAppVersion;
 }
 
 #ifdef XP_WIN
+typedef BOOL (WINAPI *IsWow64ProcessP) (HANDLE, PBOOL);
+
 #define WNT_BASE "Windows NT %ld.%ld"
 #define W64_PREFIX "; Win64"
 #endif
 
 void
 nsHttpHandler::InitUserAgentComponents()
 {
     // Gather platform.
@@ -710,17 +712,20 @@ nsHttpHandler::InitUserAgentComponents()
     if (GetVersionEx(&info)) {
         const char *format;
 #if defined _M_IA64
         format = WNT_BASE W64_PREFIX "; IA64";
 #elif defined _M_X64 || defined _M_AMD64
         format = WNT_BASE W64_PREFIX "; x64";
 #else
         BOOL isWow64 = FALSE;
-        if (!IsWow64Process(GetCurrentProcess(), &isWow64)) {
+        IsWow64ProcessP fnIsWow64Process = (IsWow64ProcessP)
+          GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
+        if (fnIsWow64Process &&
+            !fnIsWow64Process(GetCurrentProcess(), &isWow64)) {
             isWow64 = FALSE;
         }
         format = isWow64
           ? WNT_BASE "; WOW64"
           : WNT_BASE;
 #endif
         char *buf = PR_smprintf(format,
                                 info.dwMajorVersion,
--- a/netwerk/system/win32/nsNotifyAddrListener.cpp
+++ b/netwerk/system/win32/nsNotifyAddrListener.cpp
@@ -54,34 +54,77 @@
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Services.h"
 #include "nsCRT.h"
 
 #include <iptypes.h>
 #include <iphlpapi.h>
 
+typedef DWORD (WINAPI *GetAdaptersAddressesFunc)(ULONG, DWORD, PVOID,
+                                                 PIP_ADAPTER_ADDRESSES,
+                                                 PULONG);
+typedef DWORD (WINAPI *GetAdaptersInfoFunc)(PIP_ADAPTER_INFO, PULONG);
+typedef DWORD (WINAPI *GetIfEntryFunc)(PMIB_IFROW);
+typedef DWORD (WINAPI *GetIpAddrTableFunc)(PMIB_IPADDRTABLE, PULONG, BOOL);
+typedef DWORD (WINAPI *NotifyAddrChangeFunc)(PHANDLE, LPOVERLAPPED);
 typedef void (WINAPI *NcFreeNetconPropertiesFunc)(NETCON_PROPERTIES*);
 
-static HMODULE sNetshell;
+static HMODULE sIPHelper, sNetshell;
+static GetAdaptersAddressesFunc sGetAdaptersAddresses;
+static GetAdaptersInfoFunc sGetAdaptersInfo;
+static GetIfEntryFunc sGetIfEntry;
+static GetIpAddrTableFunc sGetIpAddrTable;
+static NotifyAddrChangeFunc sNotifyAddrChange;
 static NcFreeNetconPropertiesFunc sNcFreeNetconProperties;
 
+static void InitIPHelperLibrary(void)
+{
+    if (!sIPHelper) {
+        sIPHelper = LoadLibraryW(L"iphlpapi.dll");
+        if (sIPHelper) {
+            sGetAdaptersAddresses = (GetAdaptersAddressesFunc)
+                GetProcAddress(sIPHelper, "GetAdaptersAddresses");
+            sGetAdaptersInfo = (GetAdaptersInfoFunc)
+                GetProcAddress(sIPHelper, "GetAdaptersInfo");
+            sGetIfEntry = (GetIfEntryFunc)
+                GetProcAddress(sIPHelper, "GetIfEntry");
+            sGetIpAddrTable = (GetIpAddrTableFunc)
+                GetProcAddress(sIPHelper, "GetIpAddrTable");
+            sNotifyAddrChange = (NotifyAddrChangeFunc)
+                GetProcAddress(sIPHelper, "NotifyAddrChange");
+        }
+    }
+}
+
 static void InitNetshellLibrary(void)
 {
     if (!sNetshell) {
         sNetshell = LoadLibraryW(L"Netshell.dll");
         if (sNetshell) {
             sNcFreeNetconProperties = (NcFreeNetconPropertiesFunc)
                 GetProcAddress(sNetshell, "NcFreeNetconProperties");
         }
     }
 }
 
 static void FreeDynamicLibraries(void)
 {
+    if (sIPHelper)
+    {
+        sGetAdaptersAddresses = nsnull;
+        sGetAdaptersInfo = nsnull;
+        sGetIfEntry = nsnull;
+        sGetIpAddrTable = nsnull;
+        sNotifyAddrChange = nsnull;
+
+        FreeLibrary(sIPHelper);
+        sIPHelper = nsnull;
+    }
+
     if (sNetshell) {
         sNcFreeNetconProperties = nsnull;
         FreeLibrary(sNetshell);
         sNetshell = nsnull;
     }
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsNotifyAddrListener,
@@ -90,16 +133,18 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsNotifyAd
                               nsIObserver)
 
 nsNotifyAddrListener::nsNotifyAddrListener()
     : mLinkUp(true)  // assume true by default
     , mStatusKnown(false)
     , mCheckAttempted(false)
     , mShutdownEvent(nsnull)
 {
+    mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
+    GetVersionEx(&mOSVerInfo);
 }
 
 nsNotifyAddrListener::~nsNotifyAddrListener()
 {
     NS_ASSERTION(!mThread, "nsNotifyAddrListener thread shutdown failed");
     FreeDynamicLibraries();
 }
 
@@ -137,20 +182,27 @@ nsNotifyAddrListener::Run()
 {
     HANDLE ev = CreateEvent(nsnull, FALSE, FALSE, nsnull);
     NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
 
     HANDLE handles[2] = { ev, mShutdownEvent };
     OVERLAPPED overlapped = { 0 };
     bool shuttingDown = false;
 
+    InitIPHelperLibrary();
+
+    if (!sNotifyAddrChange) {
+        CloseHandle(ev);
+        return NS_ERROR_NOT_AVAILABLE;
+    }
+
     overlapped.hEvent = ev;
     while (!shuttingDown) {
         HANDLE h;
-        DWORD ret = NotifyAddrChange(&h, &overlapped);
+        DWORD ret = sNotifyAddrChange(&h, &overlapped);
 
         if (ret == ERROR_IO_PENDING) {
             ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
             if (ret == WAIT_OBJECT_0) {
                 CheckLinkStatus();
             } else {
                 shuttingDown = true;
             }
@@ -179,16 +231,21 @@ nsNotifyAddrListener::Init(void)
 {
     // XXX this call is very expensive (~650 milliseconds), so we
     //     don't want to call it synchronously.  Instead, we just
     //     start up assuming we have a network link, but we'll
     //     report that the status isn't known.
     //
     // CheckLinkStatus();
 
+    // only start a thread on Windows 2000 or later
+    if (mOSVerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+        mOSVerInfo.dwMajorVersion < 5)
+        return NS_OK;
+
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
     if (!observerService)
         return NS_ERROR_FAILURE;
 
     nsresult rv = observerService->AddObserver(this, "xpcom-shutdown-threads",
                                                false);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -252,16 +309,135 @@ nsNotifyAddrListener::ChangeEvent::Run()
         mozilla::services::GetObserverService();
     if (observerService)
         observerService->NotifyObservers(
                 mService, NS_NETWORK_LINK_TOPIC,
                 NS_ConvertASCIItoUTF16(mEventID).get());
     return NS_OK;
 }
 
+DWORD
+nsNotifyAddrListener::GetOperationalStatus(DWORD aAdapterIndex)
+{
+    DWORD status = MIB_IF_OPER_STATUS_CONNECTED;
+
+    // try to get operational status on WinNT--on Win98, it consistently gives
+    // me the wrong status, dagnabbit
+    if (mOSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+        // If this fails, assume it's connected.  Didn't find a KB, but it
+        // failed for me w/Win2K SP2, and succeeded for me w/Win2K SP3.
+        if (sGetIfEntry) {
+            MIB_IFROW ifRow;
+
+            ifRow.dwIndex = aAdapterIndex;
+            if (sGetIfEntry(&ifRow) == ERROR_SUCCESS)
+                status = ifRow.dwOperStatus;
+        }
+    }
+    return status;
+}
+
+/**
+ * Calls GetIpAddrTable to check whether a link is up.  Assumes so if any
+ * adapter has a non-zero IP (v4) address.  Sets mLinkUp if GetIpAddrTable
+ * succeeds, but doesn't set mStatusKnown.
+ * Returns ERROR_SUCCESS on success, and a Win32 error code otherwise.
+ */
+DWORD
+nsNotifyAddrListener::CheckIPAddrTable(void)
+{
+    if (!sGetIpAddrTable)
+        return ERROR_CALL_NOT_IMPLEMENTED;
+
+    ULONG size = 0;
+    DWORD ret = sGetIpAddrTable(nsnull, &size, FALSE);
+    if (ret == ERROR_INSUFFICIENT_BUFFER && size > 0) {
+        PMIB_IPADDRTABLE table = (PMIB_IPADDRTABLE) malloc(size);
+        if (!table)
+            return ERROR_OUTOFMEMORY;
+
+        ret = sGetIpAddrTable(table, &size, FALSE);
+        if (ret == ERROR_SUCCESS) {
+            bool linkUp = false;
+
+            for (DWORD i = 0; !linkUp && i < table->dwNumEntries; i++) {
+                if (GetOperationalStatus(table->table[i].dwIndex) >=
+                        MIB_IF_OPER_STATUS_CONNECTED &&
+                        table->table[i].dwAddr != 0 &&
+                        // Nor a loopback
+                        table->table[i].dwAddr != 0x0100007F)
+                    linkUp = true;
+            }
+            mLinkUp = linkUp;
+        }
+        free(table);
+    }
+    return ret;
+}
+
+/**
+ * Checks whether a link is up by calling GetAdaptersInfo.  If any adapter's
+ * operational status is at least MIB_IF_OPER_STATUS_CONNECTED, checks:
+ * 1. If it's configured for DHCP, the link is considered up if the DHCP
+ *    server is initialized.
+ * 2. If it's not configured for DHCP, the link is considered up if it has a
+ *    nonzero IP address.
+ * Sets mLinkUp and mStatusKnown if GetAdaptersInfo succeeds.
+ * Returns ERROR_SUCCESS on success, and a Win32 error code otherwise.  If the
+ * call is not present on the current platform, returns ERROR_NOT_SUPPORTED.
+ */
+DWORD
+nsNotifyAddrListener::CheckAdaptersInfo(void)
+{
+    if (!sGetAdaptersInfo)
+        return ERROR_NOT_SUPPORTED;
+
+    ULONG adaptersLen = 0;
+
+    DWORD ret = sGetAdaptersInfo(0, &adaptersLen);
+    if (ret == ERROR_BUFFER_OVERFLOW && adaptersLen > 0) {
+        PIP_ADAPTER_INFO adapters = (PIP_ADAPTER_INFO) malloc(adaptersLen);
+        if (!adapters)
+            return ERROR_OUTOFMEMORY;
+
+        ret = sGetAdaptersInfo(adapters, &adaptersLen);
+        if (ret == ERROR_SUCCESS) {
+            bool linkUp = false;
+            PIP_ADAPTER_INFO ptr;
+
+            for (ptr = adapters; ptr && !linkUp; ptr = ptr->Next) {
+                if (GetOperationalStatus(ptr->Index) >=
+                        MIB_IF_OPER_STATUS_CONNECTED) {
+                    if (ptr->DhcpEnabled) {
+                        if (PL_strcmp(ptr->DhcpServer.IpAddress.String,
+                                      "255.255.255.255")) {
+                            // it has a DHCP server, therefore it must have
+                            // a usable address
+                            linkUp = true;
+                        }
+                    }
+                    else {
+                        PIP_ADDR_STRING ipAddr;
+                        for (ipAddr = &ptr->IpAddressList; ipAddr && !linkUp;
+                             ipAddr = ipAddr->Next) {
+                            if (PL_strcmp(ipAddr->IpAddress.String, "0.0.0.0")) {
+                                linkUp = true;
+                            }
+                        }
+                    }
+                }
+            }
+            mLinkUp = linkUp;
+            mStatusKnown = true;
+            free(adapters);
+        }
+    }
+    return ret;
+}
+
 BOOL
 nsNotifyAddrListener::CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter)
 {
     if (!aAdapter->FirstUnicastAddress)
         return FALSE;
 
     LPSOCKADDR aAddress = aAdapter->FirstUnicastAddress->Address.lpSockaddr;
     if (!aAddress)
@@ -366,29 +542,32 @@ nsNotifyAddrListener::CheckICSStatus(PWC
 
 DWORD
 nsNotifyAddrListener::CheckAdaptersAddresses(void)
 {
     static const DWORD flags =
         GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_ANYCAST |
         GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
 
+    if (!sGetAdaptersAddresses)
+        return ERROR_NOT_SUPPORTED;
+
     ULONG len = 16384;
 
     PIP_ADAPTER_ADDRESSES addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
     if (!addresses)
         return ERROR_OUTOFMEMORY;
 
-    DWORD ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &len);
+    DWORD ret = sGetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &len);
     if (ret == ERROR_BUFFER_OVERFLOW) {
         free(addresses);
         addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
         if (!addresses)
             return ERROR_BUFFER_OVERFLOW;
-        ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &len);
+        ret = sGetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &len);
     }
 
     if (ret == ERROR_SUCCESS) {
         PIP_ADAPTER_ADDRESSES ptr;
         BOOL linkUp = FALSE;
 
         for (ptr = addresses; !linkUp && ptr; ptr = ptr->Next) {
             if (ptr->OperStatus == IfOperStatusUp &&
@@ -411,16 +590,20 @@ nsNotifyAddrListener::CheckAdaptersAddre
  */
 void
 nsNotifyAddrListener::CheckLinkStatus(void)
 {
     DWORD ret;
     const char *event;
 
     ret = CheckAdaptersAddresses();
+    if (ret == ERROR_NOT_SUPPORTED)
+        ret = CheckAdaptersInfo();
+    if (ret == ERROR_NOT_SUPPORTED)
+        ret = CheckIPAddrTable();
     if (ret != ERROR_SUCCESS)
         mLinkUp = true; // I can't tell, so assume there's a link
 
     if (mStatusKnown)
         event = mLinkUp ? NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN;
     else
         event = NS_NETWORK_LINK_DATA_UNKNOWN;
     SendEventToUI(event);
--- a/netwerk/system/win32/nsNotifyAddrListener.h
+++ b/netwerk/system/win32/nsNotifyAddrListener.h
@@ -76,19 +76,23 @@ protected:
 
     bool mLinkUp;
     bool mStatusKnown;
     bool mCheckAttempted;
 
     nsresult Shutdown(void);
     nsresult SendEventToUI(const char *aEventID);
 
+    DWORD GetOperationalStatus(DWORD aAdapterIndex);
+    DWORD CheckIPAddrTable(void);
+    DWORD CheckAdaptersInfo(void);
     DWORD CheckAdaptersAddresses(void);
     BOOL  CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter);
     BOOL  CheckICSStatus(PWCHAR aAdapterName);
     void  CheckLinkStatus(void);
 
     nsCOMPtr<nsIThread> mThread;
 
+    OSVERSIONINFO mOSVerInfo;
     HANDLE        mShutdownEvent;
 };
 
 #endif /* NSNOTIFYADDRLISTENER_H_ */
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -522,35 +522,34 @@ ifeq ($(OS_ARCH),SunOS)
 ifdef GNU_CC
 EXTRA_DSO_LDOPTS += -lelf
 else
 EXTRA_DSO_LDOPTS += -lelf -ldemangle
 endif
 endif
 
 ifeq ($(OS_ARCH),WINNT)
-OS_LIBS += $(call EXPAND_LIBNAME,shell32 ole32 version winspool comdlg32 imm32 msimg32 shlwapi psapi ws2_32 dbghelp rasapi32 rasdlg iphlpapi uxtheme setupapi t2embed secur32)
+OS_LIBS += $(call EXPAND_LIBNAME,shell32 ole32 uuid version winspool comdlg32 imm32 winmm wsock32 msimg32 shlwapi psapi ws2_32 dbghelp rasapi32 rasdlg)
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+OS_LIBS += $(call EXPAND_LIBNAME,imagehlp)
+endif
 ifdef MOZ_CRASHREPORTER
 OS_LIBS += $(call EXPAND_LIBNAME,wininet)
 endif
 ifdef ACCESSIBILITY
 OS_LIBS += $(call EXPAND_LIBNAME,oleacc)
 endif
 ifdef _MSC_VER
 OS_LIBS += $(call EXPAND_LIBNAME,delayimp)
 EXTRA_DSO_LDOPTS += \
   -DELAYLOAD:gkmedias.dll \
-  -DELAYLOAD:psapi.dll \
-  -DELAYLOAD:dbghelp.dll \
   -DELAYLOAD:rasapi32.dll \
   -DELAYLOAD:rasdlg.dll \
   -DELAYLOAD:comdlg32.dll \
   -DELAYLOAD:winspool.drv \
-  -DELAYLOAD:t2embed.dll \
-  -DELAYLOAD:secur32.dll \
   $(NULL)
 ifdef ACCESSIBILITY
 EXTRA_DSO_LDOPTS += -DELAYLOAD:oleacc.dll
 endif
 endif
 endif # WINNT
 
 ifdef MOZ_JPROF
--- a/toolkit/xre/nsWindowsWMain.cpp
+++ b/toolkit/xre/nsWindowsWMain.cpp
@@ -72,17 +72,17 @@ FreeAllocStrings(int argc, char **argv)
 
   delete [] argv;
 }
 
 int wmain(int argc, WCHAR **argv)
 {
 #ifndef XRE_DONT_PROTECT_DLL_LOAD
   mozilla::SanitizeEnvironmentVariables();
-  SetDllDirectoryW(L"");
+  mozilla::NS_SetDllDirectory(L"");
 #endif
 
 #ifdef XRE_WANT_DLL_BLOCKLIST
   SetupDllBlocklist();
 #endif
   
   char **argvConverted = new char*[argc + 1];
   if (!argvConverted)
--- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
@@ -242,16 +242,23 @@ nsMIMEInfoWin::GetProperty(const nsAStri
 
     rv = GetIconURLVariant(executable, _retval);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
+typedef HRESULT (STDMETHODCALLTYPE *MySHParseDisplayName)
+                 (PCWSTR pszName,
+                  IBindCtx *pbc,
+                  LPITEMIDLIST *ppidl,
+                  SFGAOF sfgaoIn,
+                  SFGAOF *psfgaoOut);
+
 // this implementation was pretty much copied verbatime from 
 // Tony Robinson's code in nsExternalProtocolWin.cpp
 nsresult
 nsMIMEInfoWin::LoadUriInternal(nsIURI * aURL)
 {
   nsresult rv = NS_OK;
 
   // 1. Find the default app for this protocol
@@ -262,46 +269,65 @@ nsMIMEInfoWin::LoadUriInternal(nsIURI * 
   // then just call ShellExecute()!
 
   if (aURL)
   {
     // extract the url spec from the url
     nsCAutoString urlSpec;
     aURL->GetAsciiSpec(urlSpec);
 
+    // Some versions of windows (Win2k before SP3, Win XP before SP1)
+    // crash in ShellExecute on long URLs (bug 161357).
+    // IE 5 and 6 support URLS of 2083 chars in length, 2K is safe
+    const PRUint32 maxSafeURL(2048);
+    if (urlSpec.Length() > maxSafeURL)
+      return NS_ERROR_FAILURE;
+
+    HMODULE hDll = NULL;
+    
     static const PRUnichar cmdVerb[] = L"open";
     SHELLEXECUTEINFOW sinfo;
     memset(&sinfo, 0, sizeof(sinfo));
     sinfo.cbSize   = sizeof(sinfo);
     sinfo.fMask    = SEE_MASK_FLAG_DDEWAIT |
       SEE_MASK_FLAG_NO_UI;
     sinfo.hwnd     = NULL;
     sinfo.lpVerb   = (LPWSTR)&cmdVerb;
     sinfo.nShow    = SW_SHOWNORMAL;
     
     LPITEMIDLIST pidl = NULL;
     SFGAOF sfgao;
     
     // Bug 394974
-    if (SUCCEEDED(SHParseDisplayName(NS_ConvertUTF8toUTF16(urlSpec).get(),
-                                     NULL, &pidl, 0, &sfgao))) {
-      sinfo.lpIDList = pidl;
-      sinfo.fMask |= SEE_MASK_INVOKEIDLIST;
+    hDll = ::LoadLibraryW(L"shell32.dll");
+    MySHParseDisplayName pMySHParseDisplayName = NULL;
+    // Version 6.0 and higher
+    if (pMySHParseDisplayName = 
+        (MySHParseDisplayName)::GetProcAddress(hDll, "SHParseDisplayName")) {
+      if (SUCCEEDED(pMySHParseDisplayName(NS_ConvertUTF8toUTF16(urlSpec).get(),
+                                          NULL, &pidl, 0, &sfgao))) {
+        sinfo.lpIDList = pidl;
+        sinfo.fMask |= SEE_MASK_INVOKEIDLIST;
+      } else {
+        // SHParseDisplayName exists, but failed. Bailing out as work around for
+        // Microsoft Security Bulletin MS07-061
+        rv = NS_ERROR_FAILURE;
+      }
     } else {
-      // SHParseDisplayName failed. Bailing out as work around for
-      // Microsoft Security Bulletin MS07-061
-      rv = NS_ERROR_FAILURE;
+      sinfo.lpFile =  NS_ConvertUTF8toUTF16(urlSpec).get();
     }
     if (NS_SUCCEEDED(rv)) {
       BOOL result = ShellExecuteExW(&sinfo);
       if (!result || ((LONG_PTR)sinfo.hInstApp) < 32)
         rv = NS_ERROR_FAILURE;
     }
     if (pidl)
       CoTaskMemFree(pidl);
+    if (hDll) 
+      ::FreeLibrary(hDll);
   }
   
   return rv;
 }
 
 // Given a path to a local file, return its nsILocalHandlerApp instance.
 bool nsMIMEInfoWin::GetLocalHandlerApp(const nsAString& aCommandHandler,
                                          nsCOMPtr<nsILocalHandlerApp>& aApp)
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -267,16 +267,41 @@ static nsresult GetKeyValue(const WCHAR*
 static void normalizeDriverId(nsString& driverid) {
   ToUpperCase(driverid);
   PRInt32 rev = driverid.Find(NS_LITERAL_CSTRING("&REV_"));
   if (rev != -1) {
     driverid.Cut(rev, driverid.Length());
   }
 }
 
+// Setup API functions
+typedef HDEVINFO (WINAPI*SetupDiGetClassDevsWFunc)(
+  CONST GUID *ClassGuid,
+  PCWSTR Enumerator,
+  HWND hwndParent,
+  DWORD Flags
+);
+typedef BOOL (WINAPI*SetupDiEnumDeviceInfoFunc)(
+  HDEVINFO DeviceInfoSet,
+  DWORD MemberIndex,
+  PSP_DEVINFO_DATA DeviceInfoData
+);
+typedef BOOL (WINAPI*SetupDiGetDeviceRegistryPropertyWFunc)(
+  HDEVINFO DeviceInfoSet,
+  PSP_DEVINFO_DATA DeviceInfoData,
+  DWORD Property,
+  PDWORD PropertyRegDataType,
+  PBYTE PropertyBuffer,
+  DWORD PropertyBufferSize,
+  PDWORD RequiredSize
+);
+typedef BOOL (WINAPI*SetupDiDestroyDeviceInfoListFunc)(
+  HDEVINFO DeviceInfoSet
+);
+
 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
 // this function is used to extract the id's out of it
 PRUint32
 ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
 {
   nsAutoString id(key);
   ToUpperCase(id);
   PRInt32 start = id.Find(prefix);
@@ -332,167 +357,190 @@ GfxInfo::Init()
     return rv;
 
   // chop off DEVICE_KEY_PREFIX
   mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
 
   mDeviceID = displayDevice.DeviceID;
   mDeviceString = displayDevice.DeviceString;
 
-  /* create a device information set composed of the current display device */
-  HDEVINFO devinfo = SetupDiGetClassDevsW(NULL, mDeviceID.get(), NULL,
-                                          DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
 
-  if (devinfo != INVALID_HANDLE_VALUE) {
-    HKEY key;
-    LONG result;
-    WCHAR value[255];
-    DWORD dwcbData;
-    SP_DEVINFO_DATA devinfoData;
-    DWORD memberIndex = 0;
+  HMODULE setupapi = LoadLibraryW(L"setupapi.dll");
 
-    devinfoData.cbSize = sizeof(devinfoData);
-    NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
-    /* enumerate device information elements in the device information set */
-    while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
-      /* get a string that identifies the device's driver key */
-      if (SetupDiGetDeviceRegistryPropertyW(devinfo,
-                                            &devinfoData,
-                                            SPDRP_DRIVER,
-                                            NULL,
-                                            (PBYTE)value,
-                                            sizeof(value),
-                                            NULL)) {
-        nsAutoString driverKey(driverKeyPre);
-        driverKey += value;
-        result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.BeginReading(), 0, KEY_QUERY_VALUE, &key);
-        if (result == ERROR_SUCCESS) {
-          /* we've found the driver we're looking for */
-          dwcbData = sizeof(value);
-          result = RegQueryValueExW(key, L"DriverVersion", NULL, NULL, (LPBYTE)value, &dwcbData);
-          if (result == ERROR_SUCCESS)
-            mDriverVersion = value;
-          dwcbData = sizeof(value);
-          result = RegQueryValueExW(key, L"DriverDate", NULL, NULL, (LPBYTE)value, &dwcbData);
-          if (result == ERROR_SUCCESS)
-            mDriverDate = value;
-          RegCloseKey(key); 
-          break;
-        }
-      }
-    }
+  if (setupapi) {
+    SetupDiGetClassDevsWFunc setupGetClassDevs = (SetupDiGetClassDevsWFunc)
+      GetProcAddress(setupapi, "SetupDiGetClassDevsW");
+    SetupDiEnumDeviceInfoFunc setupEnumDeviceInfo = (SetupDiEnumDeviceInfoFunc)
+      GetProcAddress(setupapi, "SetupDiEnumDeviceInfo");
+    SetupDiGetDeviceRegistryPropertyWFunc setupGetDeviceRegistryProperty = (SetupDiGetDeviceRegistryPropertyWFunc)
+      GetProcAddress(setupapi, "SetupDiGetDeviceRegistryPropertyW");
+    SetupDiDestroyDeviceInfoListFunc setupDestroyDeviceInfoList = (SetupDiDestroyDeviceInfoListFunc)
+      GetProcAddress(setupapi, "SetupDiDestroyDeviceInfoList");
 
-    SetupDiDestroyDeviceInfoList(devinfo);
-  }
-
-  mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
-  mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
-  mAdapterSubsysID  = ParseIDFromDeviceID(mDeviceID,  "&SUBSYS_", 8);
-
-  // We now check for second display adapter.
-
-  // Device interface class for display adapters.
-  CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
-  HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
-                               &GUID_DISPLAY_DEVICE_ARRIVAL);
-  if (hresult == NOERROR) {
-    devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL, NULL, NULL,
-                                   DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
-
-    if (devinfo != INVALID_HANDLE_VALUE) {
-      HKEY key;
-      LONG result;
-      WCHAR value[255];
-      DWORD dwcbData;
-      SP_DEVINFO_DATA devinfoData;
-      DWORD memberIndex = 0;
-      devinfoData.cbSize = sizeof(devinfoData);
+    if (setupGetClassDevs &&
+        setupEnumDeviceInfo &&
+        setupGetDeviceRegistryProperty &&
+        setupDestroyDeviceInfoList) {
+      /* create a device information set composed of the current display device */
+      HDEVINFO devinfo = setupGetClassDevs(NULL, mDeviceID.get(), NULL,
+                                           DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
 
-      nsAutoString adapterDriver2;
-      nsAutoString deviceID2;
-      nsAutoString driverVersion2;
-      nsAutoString driverDate2;
-      PRUint32 adapterVendorID2;
-      PRUint32 adapterDeviceID2;
+      if (devinfo != INVALID_HANDLE_VALUE) {
+        HKEY key;
+        LONG result;
+        WCHAR value[255];
+        DWORD dwcbData;
+        SP_DEVINFO_DATA devinfoData;
+        DWORD memberIndex = 0;
 
-      NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
-      /* enumerate device information elements in the device information set */
-      while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
-        /* get a string that identifies the device's driver key */
-        if (SetupDiGetDeviceRegistryPropertyW(devinfo,
-                                              &devinfoData,
-                                              SPDRP_DRIVER,
-                                              NULL,
-                                              (PBYTE)value,
-                                              sizeof(value),
-                                              NULL)) {
-          nsAutoString driverKey2(driverKeyPre);
-          driverKey2 += value;
-          result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.BeginReading(), 0, KEY_QUERY_VALUE, &key);
-          if (result == ERROR_SUCCESS) {
-            dwcbData = sizeof(value);
-            result = RegQueryValueExW(key, L"MatchingDeviceId", NULL, NULL, (LPBYTE)value, &dwcbData);
-            if (result != ERROR_SUCCESS) {
-              continue;
-            }
-            deviceID2 = value;
-            nsAutoString adapterVendorID2String;
-            nsAutoString adapterDeviceID2String;
-            adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
-            adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2);
-            adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
-            adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2);
-            if (mAdapterVendorID == adapterVendorID2String &&
-                mAdapterDeviceID == adapterDeviceID2String) {
-              RegCloseKey(key);
-              continue;
-            }
-
-            // If this device is missing driver information, it is unlikely to
-            // be a real display adapter.
-            if (NS_FAILED(GetKeyValue(driverKey2.BeginReading(), L"InstalledDisplayDrivers",
-                           adapterDriver2, REG_MULTI_SZ))) {
-              RegCloseKey(key);
-              continue;
-            }
-            dwcbData = sizeof(value);
-            result = RegQueryValueExW(key, L"DriverVersion", NULL, NULL, (LPBYTE)value, &dwcbData);
-            if (result != ERROR_SUCCESS) {
-              RegCloseKey(key);
-              continue;
-            }
-            driverVersion2 = value;
-            dwcbData = sizeof(value);
-            result = RegQueryValueExW(key, L"DriverDate", NULL, NULL, (LPBYTE)value, &dwcbData);
-            if (result != ERROR_SUCCESS) {
-              RegCloseKey(key);
-              continue;
-            }
-            driverDate2 = value;
-            dwcbData = sizeof(value);
-            result = RegQueryValueExW(key, L"Device Description", NULL, NULL, (LPBYTE)value, &dwcbData);
-            RegCloseKey(key);
+        devinfoData.cbSize = sizeof(devinfoData);
+        NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
+        /* enumerate device information elements in the device information set */
+        while (setupEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
+          /* get a string that identifies the device's driver key */
+          if (setupGetDeviceRegistryProperty(devinfo,
+                                             &devinfoData,
+                                             SPDRP_DRIVER,
+                                             NULL,
+                                             (PBYTE)value,
+                                             sizeof(value),
+                                             NULL)) {
+            nsAutoString driverKey(driverKeyPre);
+            driverKey += value;
+            result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.BeginReading(), 0, KEY_QUERY_VALUE, &key);
             if (result == ERROR_SUCCESS) {
-              mHasDualGPU = true;
-              mDeviceString2 = value;
-              mDeviceID2 = deviceID2;
-              mDeviceKey2 = driverKey2;
-              mDriverVersion2 = driverVersion2;
-              mDriverDate2 = driverDate2;
-              mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2);
-              mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2);
-              mAdapterSubsysID2 = ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8);
+              /* we've found the driver we're looking for */
+              dwcbData = sizeof(value);
+              result = RegQueryValueExW(key, L"DriverVersion", NULL, NULL, (LPBYTE)value, &dwcbData);
+              if (result == ERROR_SUCCESS)
+                mDriverVersion = value;
+              dwcbData = sizeof(value);
+              result = RegQueryValueExW(key, L"DriverDate", NULL, NULL, (LPBYTE)value, &dwcbData);
+              if (result == ERROR_SUCCESS)
+                mDriverDate = value;
+              RegCloseKey(key); 
               break;
             }
           }
         }
+
+        setupDestroyDeviceInfoList(devinfo);
       }
 
-      SetupDiDestroyDeviceInfoList(devinfo);
+      mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
+      mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
+      mAdapterSubsysID  = ParseIDFromDeviceID(mDeviceID,  "&SUBSYS_", 8);
+
+      // We now check for second display adapter.
+
+      // Device interface class for display adapters.
+      CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
+      HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
+                                   &GUID_DISPLAY_DEVICE_ARRIVAL);
+      if (hresult == NOERROR) {
+        devinfo = setupGetClassDevs(&GUID_DISPLAY_DEVICE_ARRIVAL, NULL, NULL,
+                                           DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
+
+        if (devinfo != INVALID_HANDLE_VALUE) {
+          HKEY key;
+          LONG result;
+          WCHAR value[255];
+          DWORD dwcbData;
+          SP_DEVINFO_DATA devinfoData;
+          DWORD memberIndex = 0;
+          devinfoData.cbSize = sizeof(devinfoData);
+
+          nsAutoString adapterDriver2;
+          nsAutoString deviceID2;
+          nsAutoString driverVersion2;
+          nsAutoString driverDate2;
+          PRUint32 adapterVendorID2;
+          PRUint32 adapterDeviceID2;
+
+          NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
+          /* enumerate device information elements in the device information set */
+          while (setupEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
+            /* get a string that identifies the device's driver key */
+            if (setupGetDeviceRegistryProperty(devinfo,
+                                               &devinfoData,
+                                               SPDRP_DRIVER,
+                                               NULL,
+                                               (PBYTE)value,
+                                               sizeof(value),
+                                               NULL)) {
+              nsAutoString driverKey2(driverKeyPre);
+              driverKey2 += value;
+              result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.BeginReading(), 0, KEY_QUERY_VALUE, &key);
+              if (result == ERROR_SUCCESS) {
+                dwcbData = sizeof(value);
+                result = RegQueryValueExW(key, L"MatchingDeviceId", NULL, NULL, (LPBYTE)value, &dwcbData);
+                if (result != ERROR_SUCCESS) {
+                  continue;
+                }
+                deviceID2 = value;
+                nsAutoString adapterVendorID2String;
+                nsAutoString adapterDeviceID2String;
+                adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
+                adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2);
+                adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
+                adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2);
+                if (mAdapterVendorID == adapterVendorID2String &&
+                    mAdapterDeviceID == adapterDeviceID2String) {
+                  RegCloseKey(key);
+                  continue;
+                }
+
+                // If this device is missing driver information, it is unlikely to
+                // be a real display adapter.
+                if (NS_FAILED(GetKeyValue(driverKey2.BeginReading(), L"InstalledDisplayDrivers",
+                               adapterDriver2, REG_MULTI_SZ))) {
+                  RegCloseKey(key);
+                  continue;
+                }
+                dwcbData = sizeof(value);
+                result = RegQueryValueExW(key, L"DriverVersion", NULL, NULL, (LPBYTE)value, &dwcbData);
+                if (result != ERROR_SUCCESS) {
+                  RegCloseKey(key);
+                  continue;
+                }
+                driverVersion2 = value;
+                dwcbData = sizeof(value);
+                result = RegQueryValueExW(key, L"DriverDate", NULL, NULL, (LPBYTE)value, &dwcbData);
+                if (result != ERROR_SUCCESS) {
+                  RegCloseKey(key);
+                  continue;
+                }
+                driverDate2 = value;
+                dwcbData = sizeof(value);
+                result = RegQueryValueExW(key, L"Device Description", NULL, NULL, (LPBYTE)value, &dwcbData);
+                RegCloseKey(key);
+                if (result == ERROR_SUCCESS) {
+                  mHasDualGPU = true;
+                  mDeviceString2 = value;
+                  mDeviceID2 = deviceID2;
+                  mDeviceKey2 = driverKey2;
+                  mDriverVersion2 = driverVersion2;
+                  mDriverDate2 = driverDate2;
+                  mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2);
+                  mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2);
+                  mAdapterSubsysID2 = ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8);
+                  break;
+                }
+              }
+            }
+          }
+
+          setupDestroyDeviceInfoList(devinfo);
+        }
+      }
+
+
     }
+
+    FreeLibrary(setupapi);
   }
 
   const char *spoofedDriverVersionString = PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
   if (spoofedDriverVersionString) {
     mDriverVersion.AssignASCII(spoofedDriverVersionString);
   }
 
   const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
@@ -753,16 +801,18 @@ GfxInfo::AddCrashReportAnnotations()
 
 #endif
 }
 
 static OperatingSystem
 WindowsVersionToOperatingSystem(PRInt32 aWindowsVersion)
 {
   switch(aWindowsVersion) {
+    case gfxWindowsPlatform::kWindows2000:
+      return DRIVER_OS_WINDOWS_2000;
     case gfxWindowsPlatform::kWindowsXP:
       return DRIVER_OS_WINDOWS_XP;
     case gfxWindowsPlatform::kWindowsServer2003:
       return DRIVER_OS_WINDOWS_SERVER_2003;
     case gfxWindowsPlatform::kWindowsVista:
       return DRIVER_OS_WINDOWS_VISTA;
     case gfxWindowsPlatform::kWindows7:
       return DRIVER_OS_WINDOWS_7;
@@ -937,16 +987,23 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
         adapterVendorID == GfxDriverInfo::GetDeviceVendor(VendorNVIDIA) &&
         adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
         driverVersion == V(6,14,11,7756))
     {
       *aStatus = FEATURE_NO_INFO;
       return NS_OK;
     }
 
+    if (aFeature == FEATURE_DIRECT3D_9_LAYERS &&
+        mWindowsVersion < gfxWindowsPlatform::kWindowsXP)
+    {
+      *aStatus = FEATURE_BLOCKED_OS_VERSION;
+      return NS_OK;
+    }
+
     // ANGLE currently uses D3D10 <-> D3D9 interop, which crashes on Optimus
     // machines.
     if (aFeature == FEATURE_WEBGL_ANGLE &&
         gfxWindowsPlatform::IsOptimus())
     {
       *aStatus = FEATURE_BLOCKED_DEVICE;
       return NS_OK;
     }
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -56,16 +56,17 @@
 class nsWindow;
 
 namespace mozilla {
 namespace widget {
 
 class WinUtils {
 public:
   enum WinVersion {
+    WIN2K_VERSION     = 0x500,
     WINXP_VERSION     = 0x501,
     WIN2K3_VERSION    = 0x502,
     VISTA_VERSION     = 0x600,
     // WIN2K8_VERSION    = VISTA_VERSION,
     WIN7_VERSION      = 0x601
     // WIN2K8R2_VERSION  = WIN7_VERSION
     // WIN8_VERSION      = 0x602
   };
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -41,48 +41,61 @@
 
 #include "nsLookAndFeel.h"
 #include <windows.h>
 #include <shellapi.h>
 #include "nsWindow.h"
 #include "nsStyleConsts.h"
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
-#include "WinUtils.h"
 
-using namespace mozilla::widget;
+typedef UINT (CALLBACK *SHAppBarMessagePtr)(DWORD, PAPPBARDATA);
+SHAppBarMessagePtr gSHAppBarMessage = NULL;
+static HINSTANCE gShell32DLLInst = NULL;
 
 static nsresult GetColorFromTheme(nsUXThemeClass cls,
                            PRInt32 aPart,
                            PRInt32 aState,
                            PRInt32 aPropId,
                            nscolor &aColor)
 {
   COLORREF color;
-  HRESULT hr = GetThemeColor(nsUXThemeData::GetTheme(cls), aPart, aState, aPropId, &color);
+  HRESULT hr = nsUXThemeData::GetThemeColor(cls, aPart, aState, aPropId, &color);
   if (hr == S_OK)
   {
     aColor = COLOREF_2_NSRGB(color);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 static PRInt32 GetSystemParam(long flag, PRInt32 def)
 {
     DWORD value; 
     return ::SystemParametersInfo(flag, 0, &value, 0) ? value : def;
 }
 
 nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel()
 {
+  gShell32DLLInst = LoadLibraryW(L"Shell32.dll");
+  if (gShell32DLLInst)
+  {
+      gSHAppBarMessage = (SHAppBarMessagePtr) GetProcAddress(gShell32DLLInst,
+                                                             "SHAppBarMessage");
+  }
 }
 
 nsLookAndFeel::~nsLookAndFeel()
 {
+   if (gShell32DLLInst)
+   {
+       FreeLibrary(gShell32DLLInst);
+       gShell32DLLInst = NULL;
+       gSHAppBarMessage = NULL;
+   }
 }
 
 nsresult
 nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
 {
   nsresult res = NS_OK;
 
   int idx;
@@ -181,27 +194,27 @@ nsLookAndFeel::NativeGetColor(ColorID aI
       idx = COLOR_GRAYTEXT;
       break;
     case eColorID_highlight:
     case eColorID__moz_html_cellhighlight:
     case eColorID__moz_menuhover:
       idx = COLOR_HIGHLIGHT;
       break;
     case eColorID__moz_menubarhovertext:
-      if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION ||
-          !IsAppThemed()) {
+      if (!nsUXThemeData::sIsVistaOrLater || !nsUXThemeData::isAppThemed())
+      {
         idx = nsUXThemeData::sFlatMenus ?
                 COLOR_HIGHLIGHTTEXT :
                 COLOR_MENUTEXT;
         break;
       }
       // Fall through
     case eColorID__moz_menuhovertext:
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-          IsAppThemed()) {
+      if (nsUXThemeData::IsAppThemed() && nsUXThemeData::sIsVistaOrLater)
+      {
         res = ::GetColorFromTheme(eUXMenu,
                                   MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
           return res;
         // fall through to highlight case
       }
     case eColorID_highlighttext:
     case eColorID__moz_html_cellhighlighttext:
@@ -266,29 +279,28 @@ nsLookAndFeel::NativeGetColor(ColorID aI
     case eColorID__moz_comboboxtext:
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_dialog:
     case eColorID__moz_cellhighlight:
       idx = COLOR_3DFACE;
       break;
     case eColorID__moz_win_mediatext:
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-          IsAppThemed()) {
+      if (nsUXThemeData::IsAppThemed() && nsUXThemeData::sIsVistaOrLater) {
         res = ::GetColorFromTheme(eUXMediaToolbar,
                                   TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
           return res;
       }
       // if we've gotten here just return -moz-dialogtext instead
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_win_communicationstext:
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-          IsAppThemed()) {
+      if (nsUXThemeData::IsAppThemed() && nsUXThemeData::sIsVistaOrLater)
+      {
         res = ::GetColorFromTheme(eUXCommunicationsToolbar,
                                   TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
         if (NS_SUCCEEDED(res))
           return res;
       }
       // if we've gotten here just return -moz-dialogtext instead
       idx = COLOR_WINDOWTEXT;
       break;
@@ -388,17 +400,17 @@ nsLookAndFeel::GetIntImpl(IntID aID, PRI
         break;
     case eIntID_TreeScrollDelay:
         aResult = 100;
         break;
     case eIntID_TreeScrollLinesMax:
         aResult = 3;
         break;
     case eIntID_WindowsClassic:
-        aResult = !IsAppThemed();
+        aResult = !nsUXThemeData::IsAppThemed();
         break;
     case eIntID_TouchEnabled:
         aResult = 0;
         PRInt32 touchCapabilities;
         touchCapabilities = ::GetSystemMetrics(SM_DIGITIZER);
         if ((touchCapabilities & NID_READY) && 
            (touchCapabilities & (NID_EXTERNAL_TOUCH | NID_INTEGRATED_TOUCH))) {
             aResult = 1;
@@ -416,27 +428,28 @@ nsLookAndFeel::GetIntImpl(IntID aID, PRI
         aResult = 0;
         res = NS_ERROR_NOT_IMPLEMENTED;
         break;
     case eIntID_DWMCompositor:
         aResult = nsUXThemeData::CheckForCompositor();
         break;
     case eIntID_AlertNotificationOrigin:
         aResult = 0;
+        if (gSHAppBarMessage)
         {
           // Get task bar window handle
           HWND shellWindow = FindWindowW(L"Shell_TrayWnd", NULL);
 
           if (shellWindow != NULL)
           {
             // Determine position
             APPBARDATA appBarData;
             appBarData.hWnd = shellWindow;
             appBarData.cbSize = sizeof(appBarData);
-            if (SHAppBarMessage(ABM_GETTASKBARPOS, &appBarData))
+            if (gSHAppBarMessage(ABM_GETTASKBARPOS, &appBarData))
             {
               // Set alert origin as a bit field - see LookAndFeel.h
               // 0 represents bottom right, sliding vertically.
               switch(appBarData.uEdge)
               {
                 case ABE_LEFT:
                   aResult = NS_ALERT_HORIZONTAL | NS_ALERT_LEFT;
                   break;
@@ -501,10 +514,16 @@ nsLookAndFeel::GetFloatImpl(FloatID aID,
   return res;
 }
 
 /* virtual */
 PRUnichar
 nsLookAndFeel::GetPasswordCharacterImpl()
 {
 #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf
-  return UNICODE_BLACK_CIRCLE_CHAR;
+  static PRUnichar passwordCharacter = 0;
+  if (!passwordCharacter) {
+    passwordCharacter = '*';
+    if (nsUXThemeData::sIsXPOrLater)
+      passwordCharacter = UNICODE_BLACK_CIRCLE_CHAR;
+  }
+  return passwordCharacter;
 }
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -161,23 +161,23 @@ static bool IsTopLevelMenu(nsIFrame *aFr
     isTopLevel = menuFrame->IsOnMenuBar();
   }
   return isTopLevel;
 }
 
 static MARGINS GetCheckboxMargins(HANDLE theme, HDC hdc)
 {
     MARGINS checkboxContent = {0};
-    GetThemeMargins(theme, hdc, MENU_POPUPCHECK, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxContent);
+    nsUXThemeData::getThemeMargins(theme, hdc, MENU_POPUPCHECK, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxContent);
     return checkboxContent;
 }
 static SIZE GetCheckboxBGSize(HANDLE theme, HDC hdc)
 {
     SIZE checkboxSize;
-    GetThemePartSize(theme, hdc, MENU_POPUPCHECK, MC_CHECKMARKNORMAL, NULL, TS_TRUE, &checkboxSize);
+    nsUXThemeData::getThemePartSize(theme, hdc, MENU_POPUPCHECK, MC_CHECKMARKNORMAL, NULL, TS_TRUE, &checkboxSize);
 
     MARGINS checkboxMargins = GetCheckboxMargins(theme, hdc);
 
     int leftMargin = checkboxMargins.cxLeftWidth;
     int rightMargin = checkboxMargins.cxRightWidth;
     int topMargin = checkboxMargins.cyTopHeight;
     int bottomMargin = checkboxMargins.cyBottomHeight;
 
@@ -187,40 +187,40 @@ static SIZE GetCheckboxBGSize(HANDLE the
     ret.cx = width;
     ret.cy = height;
     return ret;
 }
 static SIZE GetCheckboxBGBounds(HANDLE theme, HDC hdc)
 {
     MARGINS checkboxBGSizing = {0};
     MARGINS checkboxBGContent = {0};
-    GetThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_SIZINGMARGINS, NULL, &checkboxBGSizing);
-    GetThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxBGContent);
+    nsUXThemeData::getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_SIZINGMARGINS, NULL, &checkboxBGSizing);
+    nsUXThemeData::getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxBGContent);
 
 #define posdx(d) ((d) > 0 ? d : 0)
 
     int dx = posdx(checkboxBGContent.cxRightWidth - checkboxBGSizing.cxRightWidth) + posdx(checkboxBGContent.cxLeftWidth - checkboxBGSizing.cxLeftWidth);
     int dy = posdx(checkboxBGContent.cyTopHeight - checkboxBGSizing.cyTopHeight) + posdx(checkboxBGContent.cyBottomHeight - checkboxBGSizing.cyBottomHeight);
 
 #undef posdx
 
     SIZE ret(GetCheckboxBGSize(theme, hdc));
     ret.cx += dx;
     ret.cy += dy;
     return ret;
 }
 static SIZE GetGutterSize(HANDLE theme, HDC hdc)
 {
     SIZE gutterSize;
-    GetThemePartSize(theme, hdc, MENU_POPUPGUTTER, 0, NULL, TS_TRUE, &gutterSize);
+    nsUXThemeData::getThemePartSize(theme, hdc, MENU_POPUPGUTTER, 0, NULL, TS_TRUE, &gutterSize);
 
     SIZE checkboxBGSize(GetCheckboxBGBounds(theme, hdc));
 
     SIZE itemSize;
-    GetThemePartSize(theme, hdc, MENU_POPUPITEM, MPI_NORMAL, NULL, TS_TRUE, &itemSize);
+    nsUXThemeData::getThemePartSize(theme, hdc, MENU_POPUPITEM, MPI_NORMAL, NULL, TS_TRUE, &itemSize);
 
     int width = NS_MAX(itemSize.cx, checkboxBGSize.cx + gutterSize.cx);
     int height = NS_MAX(itemSize.cy, checkboxBGSize.cy);
     SIZE ret;
     ret.cx = width;
     ret.cy = height;
     return ret;
 }
@@ -271,26 +271,26 @@ static HRESULT DrawThemeBGRTLAware(HANDL
         newCRect.top = clipRect->top;
         newCRect.bottom = clipRect->bottom;
         newCRect.left = bitmap.bmWidth - (clipRect->right + 2*vpOrg.x);
         newCRect.right = bitmap.bmWidth - (clipRect->left + 2*vpOrg.x);
         newCRectPtr = &newCRect;
       }
 
       SetLayout(hdc, LAYOUT_RTL);
-      HRESULT hr = DrawThemeBackground(theme, hdc, part, state, &newWRect, newCRectPtr);
+      HRESULT hr = nsUXThemeData::drawThemeBG(theme, hdc, part, state, &newWRect, newCRectPtr);
       SetLayout(hdc, 0);
 
       if (hr == S_OK)
         return hr;
     }
   }
 
   // Draw normally if LTR or if anything went wrong
-  return DrawThemeBackground(theme, hdc, part, state, widgetRect, clipRect);
+  return nsUXThemeData::drawThemeBG(theme, hdc, part, state, widgetRect, clipRect);
 }
 
 /*
   Caption button padding data - 'hot' button padding.
   These areas are considered hot, in that they activate
   a button when hovered or clicked. The button graphic
   is drawn inside the padding border. Unrecognized themes
   are treated as their recognized counterparts for now.
@@ -378,46 +378,46 @@ static const PRInt32 kProgressIndetermin
 // Delay (in ms) between two determinate progress bar animation on Vista/7.
 static const PRInt32 kProgressDeterminedVistaDelay = 1000;
 
 // Adds "hot" caption button padding to minimum widget size.
 static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
   if (!aSize)
     return;
   RECT offset;
-  if (!IsAppThemed())
+  if (!nsUXThemeData::IsAppThemed())
     offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
   else if (WinUtils::GetWindowsVersion() == WinUtils::WINXP_VERSION)
     offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   else
     offset = buttonData[CAPTION_BASIC].hotPadding[button];
   aSize->width += offset.left + offset.right;
   aSize->height += offset.top + offset.bottom;
 }
 
 // If we've added padding to the minimum widget size, offset
 // the area we draw into to compensate.
 static void OffsetBackgroundRect(RECT& rect, CaptionButton button) {
   RECT offset;
-  if (!IsAppThemed())
+  if (!nsUXThemeData::IsAppThemed())
     offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
   else if (WinUtils::GetWindowsVersion() == WinUtils::WINXP_VERSION)
     offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
   else
     offset = buttonData[CAPTION_BASIC].hotPadding[button];
   rect.left += offset.left;
   rect.top += offset.top;
   rect.right -= offset.right;
   rect.bottom -= offset.bottom;
 }
 
 HANDLE
 nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
 { 
-  if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION) {
+  if (!nsUXThemeData::sIsVistaOrLater) {
     // 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_DROPDOWN)
       aWidgetType = NS_THEME_TEXTFIELD;
   }
 
@@ -426,19 +426,18 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidg
     case NS_THEME_RADIO:
     case NS_THEME_CHECKBOX:
     case NS_THEME_GROUPBOX:
       return nsUXThemeData::GetTheme(eUXButton);
     case NS_THEME_TEXTFIELD:
     case NS_THEME_TEXTFIELD_MULTILINE:
       return nsUXThemeData::GetTheme(eUXEdit);
     case NS_THEME_TOOLTIP:
-      // XP/2K3 should force a classic treatment of tooltips
-      return WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION ?
-        NULL : nsUXThemeData::GetTheme(eUXTooltip);
+      // BUG #161600: XP/2K3 should force a classic treatment of tooltips
+      return nsUXThemeData::sIsVistaOrLater ? nsUXThemeData::GetTheme(eUXTooltip) : NULL;
     case NS_THEME_TOOLBOX:
       return nsUXThemeData::GetTheme(eUXRebar);
     case NS_THEME_WIN_MEDIA_TOOLBOX:
       return nsUXThemeData::GetTheme(eUXMediaRebar);
     case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX:
       return nsUXThemeData::GetTheme(eUXCommunicationsRebar);
     case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX:
       return nsUXThemeData::GetTheme(eUXBrowserTabBarRebar);
@@ -553,17 +552,17 @@ nsNativeThemeWin::IsMenuActive(nsIFrame 
  * us; 0 means that we should use part code 0, which isn't a real part code
  * but elicits some kind of default behaviour from UXTheme when drawing
  * (but isThemeBackgroundPartiallyTransparent may not work).
  */
 nsresult 
 nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, 
                                        PRInt32& aPart, PRInt32& aState)
 {
-  if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION) {
+  if (!nsUXThemeData::sIsVistaOrLater) {
     // See GetTheme
     if (aWidgetType == NS_THEME_DROPDOWN)
       aWidgetType = NS_THEME_TEXTFIELD;
   }
 
   switch (aWidgetType) {
     case NS_THEME_BUTTON: {
       aPart = BP_BUTTON;
@@ -630,17 +629,17 @@ nsNativeThemeWin::GetThemePartAndState(n
       // Since we don't support groupbox disabled and GBS_DISABLED looks the
       // same as GBS_NORMAL don't bother supporting GBS_DISABLED.
       return NS_OK;
     }
     case NS_THEME_TEXTFIELD:
     case NS_THEME_TEXTFIELD_MULTILINE: {
       nsEventStates eventState = GetContentState(aFrame, aWidgetType);
 
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+      if (nsUXThemeData::sIsVistaOrLater) {
         /* 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.
          */
@@ -697,21 +696,19 @@ nsNativeThemeWin::GetThemePartAndState(n
       nsIFrame* stateFrame = aFrame->GetParent();
       nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
 
       if (IsIndeterminateProgress(stateFrame, eventStates)) {
         // If the element is indeterminate, we are going to render it ourself so
         // we have to return aPart = -1.
         aPart = -1;
       } else if (IsVerticalProgress(stateFrame)) {
-        aPart = WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION ?
-          PP_FILLVERT : PP_CHUNKVERT;
+        aPart = nsUXThemeData::sIsVistaOrLater ? PP_FILLVERT : PP_CHUNKVERT;
       } else {
-        aPart = WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION ?
-          PP_FILL : PP_CHUNK;
+        aPart = nsUXThemeData::sIsVistaOrLater ? PP_FILL : PP_CHUNK;
       }
 
       aState = TS_NORMAL;
       return NS_OK;
     }
     case NS_THEME_PROGRESSBAR_VERTICAL: {
       aPart = PP_BARVERT;
       aState = TS_NORMAL;
@@ -774,18 +771,17 @@ nsNativeThemeWin::GetThemePartAndState(n
         aState += TS_DISABLED;
       else {
         nsIFrame *parent = aFrame->GetParent();
         nsEventStates parentState = GetContentState(parent, parent->GetStyleDisplay()->mAppearance);
         if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
           aState += TS_ACTIVE;
         else if (eventState.HasState(NS_EVENT_STATE_HOVER))
           aState += TS_HOVER;
-        else if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-                 parentState.HasState(NS_EVENT_STATE_HOVER))
+        else if (nsUXThemeData::sIsVistaOrLater && parentState.HasState(NS_EVENT_STATE_HOVER))
           aState = (aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP) + SP_BUTTON_IMPLICIT_HOVER_BASE;
         else
           aState += TS_NORMAL;
       }
       return NS_OK;
     }
     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
     case NS_THEME_SCROLLBAR_TRACK_VERTICAL: {
@@ -863,17 +859,17 @@ nsNativeThemeWin::GetThemePartAndState(n
     case NS_THEME_TOOLBOX:
     case NS_THEME_WIN_MEDIA_TOOLBOX:
     case NS_THEME_WIN_COMMUNICATIONS_TOOLBOX:
     case NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX:
     case NS_THEME_STATUSBAR:
     case NS_THEME_SCROLLBAR:
     case NS_THEME_SCROLLBAR_SMALL: {
       aState = 0;
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+      if (nsUXThemeData::sIsVistaOrLater) {
         // 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;
@@ -995,18 +991,17 @@ nsNativeThemeWin::GetThemePartAndState(n
       bool isMenulist = !isHTML && parentFrame->GetType() == nsGkAtoms::menuFrame;
       bool isOpen = false;
 
       // HTML select and XUL menulist dropdown buttons get state from the parent.
       if (isHTML || isMenulist)
         aFrame = parentFrame;
 
       nsEventStates eventState = GetContentState(aFrame, aWidgetType);
-      aPart = WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION ?
-        CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
+      aPart = nsUXThemeData::sIsVistaOrLater ? CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
 
       // For HTML controls with author styling, we should fall
       // back to the old dropmarker style to avoid clashes with
       // author-specified backgrounds and borders (bug #441034)
       if (isHTML && IsWidgetStyled(aFrame->PresContext(), aFrame, NS_THEME_DROPDOWN))
         aPart = CBP_DROPMARKER;
 
       if (IsDisabled(aFrame, eventState)) {
@@ -1016,17 +1011,17 @@ nsNativeThemeWin::GetThemePartAndState(n
 
       if (isHTML) {
         nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
         isOpen = (ccf && ccf->IsDroppedDown());
       }
       else
         isOpen = IsOpenButton(aFrame);
 
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+      if (nsUXThemeData::sIsVistaOrLater) {
         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.
@@ -1212,16 +1207,19 @@ nsNativeThemeWin::DrawWidgetBackground(n
                                        PRUint8 aWidgetType,
                                        const nsRect& aRect,
                                        const nsRect& aDirtyRect)
 {
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
 
+  if (!nsUXThemeData::drawThemeBG)
+    return NS_ERROR_FAILURE;    
+
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
   // ^^ without the right sdk, assume xp theming and fall through.
   if (nsUXThemeData::CheckForCompositor()) {
     switch (aWidgetType) {
       case NS_THEME_WINDOW_TITLEBAR:
       case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
       case NS_THEME_WINDOW_FRAME_LEFT:
       case NS_THEME_WINDOW_FRAME_RIGHT:
@@ -1350,35 +1348,35 @@ RENDER_AGAIN:
   }
 
   // widgetRect is the bounding box for a widget, yet the scale track is only
   // a small portion of this size, so the edges of the scale need to be
   // adjusted to the real size of the track.
   if (aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
       aWidgetType == NS_THEME_SCALE_VERTICAL) {
     RECT contentRect;
-    GetThemeBackgroundContentRect(theme, hdc, part, state, &widgetRect, &contentRect);
+    nsUXThemeData::getThemeContentRect(theme, hdc, part, state, &widgetRect, &contentRect);
 
     SIZE siz;
-    GetThemePartSize(theme, hdc, part, state, &widgetRect, TS_TRUE, &siz);
+    nsUXThemeData::getThemePartSize(theme, hdc, part, state, &widgetRect, 1, &siz);
 
     if (aWidgetType == NS_THEME_SCALE_HORIZONTAL) {
       PRInt32 adjustment = (contentRect.bottom - contentRect.top - siz.cy) / 2 + 1;
       contentRect.top += adjustment;
       contentRect.bottom -= adjustment;
     }
     else {
       PRInt32 adjustment = (contentRect.right - contentRect.left - siz.cx) / 2 + 1;
       // need to subtract one from the left position, otherwise the scale's
       // border isn't visible
       contentRect.left += adjustment - 1;
       contentRect.right -= adjustment;
     }
 
-    DrawThemeBackground(theme, hdc, part, state, &contentRect, &clipRect);
+    nsUXThemeData::drawThemeBG(theme, hdc, part, state, &contentRect, &clipRect);
   }
   else if (aWidgetType == NS_THEME_MENUCHECKBOX || aWidgetType == NS_THEME_MENURADIO)
   {
       bool isChecked = false;
       isChecked = CheckBooleanAttr(aFrame, nsGkAtoms::checked);
 
       if (isChecked)
       {
@@ -1397,40 +1395,40 @@ RENDER_AGAIN:
         } else {
           checkBGRect.right = checkBGRect.left+checkboxBGSize.cx;
         }
 
         // Center the checkbox background vertically in the menuitem
         checkBGRect.top += (checkBGRect.bottom - checkBGRect.top)/2 - checkboxBGSize.cy/2;
         checkBGRect.bottom = checkBGRect.top + checkboxBGSize.cy;
 
-        DrawThemeBackground(theme, hdc, MENU_POPUPCHECKBACKGROUND, bgState, &checkBGRect, &clipRect);
+        nsUXThemeData::drawThemeBG(theme, hdc, MENU_POPUPCHECKBACKGROUND, bgState, &checkBGRect, &clipRect);
 
         MARGINS checkMargins = GetCheckboxMargins(theme, hdc);
         RECT checkRect = checkBGRect;
         checkRect.left += checkMargins.cxLeftWidth;
         checkRect.right -= checkMargins.cxRightWidth;
         checkRect.top += checkMargins.cyTopHeight;
         checkRect.bottom -= checkMargins.cyBottomHeight;
-        DrawThemeBackground(theme, hdc, MENU_POPUPCHECK, state, &checkRect, &clipRect);
+        nsUXThemeData::drawThemeBG(theme, hdc, MENU_POPUPCHECK, state, &checkRect, &clipRect);
       }
   }
   else if (aWidgetType == NS_THEME_MENUPOPUP)
   {
-    DrawThemeBackground(theme, hdc, MENU_POPUPBORDERS, /* state */ 0, &widgetRect, &clipRect);
+    nsUXThemeData::drawThemeBG(theme, hdc, MENU_POPUPBORDERS, /* state */ 0, &widgetRect, &clipRect);
     SIZE borderSize;
-    GetThemePartSize(theme, hdc, MENU_POPUPBORDERS, 0, NULL, TS_TRUE, &borderSize);
+    nsUXThemeData::getThemePartSize(theme, hdc, MENU_POPUPBORDERS, 0, NULL, TS_TRUE, &borderSize);
 
     RECT bgRect = widgetRect;
     bgRect.top += borderSize.cy;
     bgRect.bottom -= borderSize.cy;
     bgRect.left += borderSize.cx;
     bgRect.right -= borderSize.cx;
 
-    DrawThemeBackground(theme, hdc, MENU_POPUPBACKGROUND, /* state */ 0, &bgRect, &clipRect);
+    nsUXThemeData::drawThemeBG(theme, hdc, MENU_POPUPBACKGROUND, /* state */ 0, &bgRect, &clipRect);
 
     SIZE gutterSize(GetGutterSize(theme, hdc));
 
     RECT gutterRect;
     gutterRect.top = bgRect.top;
     gutterRect.bottom = bgRect.bottom;
     if (IsFrameRTL(aFrame)) {
       gutterRect.right = bgRect.right;
@@ -1448,30 +1446,30 @@ RENDER_AGAIN:
     SIZE gutterSize(GetGutterSize(theme,hdc));
 
     RECT sepRect = widgetRect;
     if (IsFrameRTL(aFrame))
       sepRect.right -= gutterSize.cx;
     else
       sepRect.left += gutterSize.cx;
 
-    DrawThemeBackground(theme, hdc, MENU_POPUPSEPARATOR, /* state */ 0, &sepRect, &clipRect);
+    nsUXThemeData::drawThemeBG(theme, hdc, MENU_POPUPSEPARATOR, /* state */ 0, &sepRect, &clipRect);
   }
   // The following widgets need to be RTL-aware
   else if (aWidgetType == NS_THEME_MENUARROW ||
            aWidgetType == NS_THEME_RESIZER ||
            aWidgetType == NS_THEME_DROPDOWN_BUTTON)
   {
     DrawThemeBGRTLAware(theme, hdc, part, state,
                         &widgetRect, &clipRect, IsFrameRTL(aFrame));
   }
   // If part is negative, the element wishes us to not render a themed
   // background, instead opting to be drawn specially below.
   else if (part >= 0) {
-    DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
+    nsUXThemeData::drawThemeBG(theme, hdc, part, state, &widgetRect, &clipRect);
   }
 
   // Draw focus rectangles for XP HTML checkboxes and radio buttons
   // XXX it'd be nice to draw these outside of the frame
   if (((aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO) &&
         aFrame->GetContent()->IsHTML()) ||
       aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
       aWidgetType == NS_THEME_SCALE_VERTICAL) {
@@ -1484,18 +1482,17 @@ RENDER_AGAIN:
         PRUint8 id = SaveDC(hdc);
 
         ::SelectClipRgn(hdc, NULL);
         ::GetViewportOrgEx(hdc, &vpOrg);
         ::SetBrushOrgEx(hdc, vpOrg.x + widgetRect.left, vpOrg.y + widgetRect.top, NULL);
 
         // On vista, choose our own colors and draw an XP style half focus rect
         // for focused checkboxes and a full rect when active.
-        if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-            aWidgetType == NS_THEME_CHECKBOX) {
+        if (nsUXThemeData::sIsVistaOrLater && aWidgetType == NS_THEME_CHECKBOX) {
           LOGBRUSH lb;
           lb.lbStyle = BS_SOLID;
           lb.lbColor = RGB(255,255,255);
           lb.lbHatch = 0;
 
           hPen = ::ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
           ::SelectObject(hdc, hPen);
 
@@ -1523,34 +1520,34 @@ RENDER_AGAIN:
   else if (aWidgetType == NS_THEME_TOOLBAR && state == 0) {
     // Draw toolbar separator lines above all toolbars except the first one.
     // The lines are part of the Rebar theme, which is loaded for NS_THEME_TOOLBOX.
     theme = GetTheme(NS_THEME_TOOLBOX);
     if (!theme)
       return NS_ERROR_FAILURE;
 
     widgetRect.bottom = widgetRect.top + TB_SEPARATOR_HEIGHT;
-    DrawThemeEdge(theme, hdc, RP_BAND, 0, &widgetRect, EDGE_ETCHED, BF_TOP, NULL);
+    nsUXThemeData::drawThemeEdge(theme, hdc, RP_BAND, 0, &widgetRect, EDGE_ETCHED, BF_TOP, NULL);
   }
   else if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL ||
            aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL)
   {
     // Draw the decorative gripper for the scrollbar thumb button, if it fits
 
     SIZE gripSize;
     MARGINS thumbMgns;
     int gripPart = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) ?
                    SP_GRIPPERHOR : SP_GRIPPERVERT;
 
-    if (GetThemePartSize(theme, hdc, gripPart, state, NULL, TS_TRUE, &gripSize) == S_OK &&
-        GetThemeMargins(theme, hdc, part, state, TMT_CONTENTMARGINS, NULL, &thumbMgns) == S_OK &&
+    if (nsUXThemeData::getThemePartSize(theme, hdc, gripPart, state, NULL, TS_TRUE, &gripSize) == S_OK &&
+        nsUXThemeData::getThemeMargins(theme, hdc, part, state, TMT_CONTENTMARGINS, NULL, &thumbMgns) == S_OK &&
         gripSize.cx + thumbMgns.cxLeftWidth + thumbMgns.cxRightWidth <= widgetRect.right - widgetRect.left &&
         gripSize.cy + thumbMgns.cyTopHeight + thumbMgns.cyBottomHeight <= widgetRect.bottom - widgetRect.top)
     {
-      DrawThemeBackground(theme, hdc, gripPart, state, &widgetRect, &clipRect);
+      nsUXThemeData::drawThemeBG(theme, hdc, gripPart, state, &widgetRect, &clipRect);
     }
   }
   else if ((aWidgetType == NS_THEME_WINDOW_BUTTON_BOX ||
             aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) &&
             nsUXThemeData::CheckForCompositor())
   {
     // The caption buttons are drawn by the DWM, we just need to clear the area where they
     // are because we might have drawn something above them (like a background-image).
@@ -1594,30 +1591,29 @@ RENDER_AGAIN:
      * When the progress bar is determinated, the animated part is a glow draw
      * on top of the background (PP_FILL).
      */
     nsIFrame* stateFrame = aFrame->GetParent();
     nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
     bool indeterminate = IsIndeterminateProgress(stateFrame, eventStates);
     bool vertical = IsVerticalProgress(stateFrame);
 
-    if (indeterminate ||
-        WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+    if (indeterminate || nsUXThemeData::sIsVistaOrLater) {
       if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
         NS_WARNING("unable to animate progress widget!");
       }
 
       /**
        * Unfortunately, vertical progress bar support on Windows seems weak and
        * PP_MOVEOVERLAYRECT looks really different from PP_MOVEOVERLAY.
        * Thus, we have to change the size and even don't use it for vertical
        * indeterminate progress bars.
        */
       PRInt32 overlaySize;
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+      if (nsUXThemeData::sIsVistaOrLater) {
         if (vertical) {
           overlaySize = indeterminate ? kProgressVerticalIndeterminateOverlaySize
                                       : kProgressVerticalOverlaySize;
         } else {
           overlaySize = kProgressHorizontalVistaOverlaySize;
         }
       } else {
         overlaySize = kProgressHorizontalXPOverlaySize;
@@ -1651,27 +1647,26 @@ RENDER_AGAIN:
         overlayRect.top = overlayRect.bottom - overlaySize;
       } else {
         overlayRect.left += dx;
         overlayRect.right = overlayRect.left + overlaySize;
       }
 
       PRInt32 overlayPart;
       if (vertical) {
-        if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+        if (nsUXThemeData::sIsVistaOrLater) {
           overlayPart = indeterminate ? PP_MOVEOVERLAY : PP_MOVEOVERLAYVERT;
         } else {
           overlayPart = PP_CHUNKVERT;
         }
       } else {
-        overlayPart = WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION ?
-          PP_MOVEOVERLAY : PP_CHUNK;
+        overlayPart = nsUXThemeData::sIsVistaOrLater ? PP_MOVEOVERLAY : PP_CHUNK;
       }
 
-      DrawThemeBackground(theme, hdc, overlayPart, state, &overlayRect,
+      nsUXThemeData::drawThemeBG(theme, hdc, overlayPart, state, &overlayRect,
                                  &clipRect);
     }
   }
 
 
   nativeDrawing.EndNativeDrawing();
 
   if (nativeDrawing.ShouldRenderAgain())
@@ -1707,16 +1702,19 @@ nsNativeThemeWin::GetWidgetBorder(nsDevi
       aWidgetType == NS_THEME_RADIOMENUITEM || aWidgetType == NS_THEME_MENUPOPUP ||
       aWidgetType == NS_THEME_MENUIMAGE || aWidgetType == NS_THEME_MENUITEMTEXT ||
       aWidgetType == NS_THEME_TOOLBAR_SEPARATOR ||
       aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
       aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED ||
       aWidgetType == NS_THEME_WIN_GLASS || aWidgetType == NS_THEME_WIN_BORDERLESS_GLASS)
     return NS_OK; // Don't worry about it.
 
+  if (!nsUXThemeData::getThemeContentRect)
+    return NS_ERROR_FAILURE;
+
   PRInt32 part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   if (NS_FAILED(rv))
     return rv;
 
   if (aWidgetType == NS_THEME_TOOLBAR) {
     // make space for the separator line above all toolbars but the first
     if (state == 0)
@@ -1724,17 +1722,17 @@ nsNativeThemeWin::GetWidgetBorder(nsDevi
     return NS_OK;
   }
 
   // Get our info.
   RECT outerRect; // Create a fake outer rect.
   outerRect.top = outerRect.left = 100;
   outerRect.right = outerRect.bottom = 200;
   RECT contentRect(outerRect);
-  HRESULT res = GetThemeBackgroundContentRect(theme, NULL, part, state, &outerRect, &contentRect);
+  HRESULT res = nsUXThemeData::getThemeContentRect(theme, NULL, part, state, &outerRect, &contentRect);
   
   if (FAILED(res))
     return NS_ERROR_FAILURE;
 
   // Now compute the delta in each direction and place it in our
   // nsIntMargin struct.
   aResult->top = contentRect.top - outerRect.top;
   aResult->bottom = outerRect.bottom - contentRect.bottom;
@@ -1814,23 +1812,23 @@ nsNativeThemeWin::GetWidgetPadding(nsDev
   }
 
   if (!theme)
     return ClassicGetWidgetPadding(aContext, aFrame, aWidgetType, aResult);
 
   if (aWidgetType == NS_THEME_MENUPOPUP)
   {
     SIZE popupSize;
-    GetThemePartSize(theme, NULL, MENU_POPUPBORDERS, /* state */ 0, NULL, TS_TRUE, &popupSize);
+    nsUXThemeData::getThemePartSize(theme, NULL, MENU_POPUPBORDERS, /* state */ 0, NULL, TS_TRUE, &popupSize);
     aResult->top = aResult->bottom = popupSize.cy;
     aResult->left = aResult->right = popupSize.cx;
     return true;
   }
 
-  if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+  if (nsUXThemeData::sIsVistaOrLater) {
     if (aWidgetType == NS_THEME_TEXTFIELD ||
         aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
         aWidgetType == NS_THEME_DROPDOWN)
     {
       /* 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;
     }
@@ -1913,17 +1911,17 @@ nsNativeThemeWin::GetWidgetOverflow(nsDe
   /* This is disabled for now, because it causes invalidation problems --
    * see bug 420381.  The effect of not updating the overflow area is that
    * for dropdown buttons in content areas, there is a 1px border on 3 sides
    * where, if invalidated, the dropdown control probably won't be repainted.
    * This is fairly minor, as by default there is nothing in that area, and
    * a border only shows up if the widget is being hovered.
    */
 #if 0
-  if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+  if (nsUXThemeData::sIsVistaOrLater) {
     /* 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_DROPDOWN_BUTTON &&
         IsHTMLContent(aFrame) &&
         !IsWidgetStyled(aFrame->GetParent()->PresContext(),
                         aFrame->GetParent(),
@@ -1972,20 +1970,23 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
     case NS_THEME_WIN_GLASS:
     case NS_THEME_WIN_BORDERLESS_GLASS:
       return NS_OK; // Don't worry about it.
   }
 
   if (aWidgetType == NS_THEME_MENUITEM && IsTopLevelMenu(aFrame))
       return NS_OK; // Don't worry about it for top level menus
 
+  if (!nsUXThemeData::getThemePartSize)
+    return NS_ERROR_FAILURE;
+  
   // Call GetSystemMetrics to determine size for WinXP scrollbars
   // (GetThemeSysSize API returns the optimal size for the theme, but 
   //  Windows appears to always use metrics when drawing standard scrollbars)
-  THEMESIZE sizeReq = TS_TRUE; // Best-fit size
+  PRInt32 sizeReq = TS_TRUE; // Best-fit size
   switch (aWidgetType) {
     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
     case NS_THEME_SCROLLBAR_BUTTON_UP:
     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
@@ -2036,17 +2037,17 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
       break;
 
     case NS_THEME_SCALE_THUMB_HORIZONTAL:
     case NS_THEME_SCALE_THUMB_VERTICAL:
     {
       *aIsOverridable = false;
       // on Vista, GetThemePartAndState returns odd values for
       // scale thumbs, so use a hardcoded size instead.
-      if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
+      if (nsUXThemeData::sIsVistaOrLater) {
         if (aWidgetType == NS_THEME_SCALE_THUMB_HORIZONTAL) {
           aResult->width = 12;
           aResult->height = 20;
         }
         else {
           aResult->width = 20;
           aResult->height = 12;
         }
@@ -2149,17 +2150,17 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
   if (NS_FAILED(rv))
     return rv;
 
   HDC hdc = gfxWindowsPlatform::GetPlatform()->GetScreenDC();
   if (!hdc)
     return NS_ERROR_FAILURE;
 
   SIZE sz;
-  GetThemePartSize(theme, hdc, part, state, NULL, sizeReq, &sz);
+  nsUXThemeData::getThemePartSize(theme, hdc, part, state, NULL, sizeReq, &sz);
   aResult->width = sz.cx;
   aResult->height = sz.cy;
 
   switch(aWidgetType) {
     case NS_THEME_SPINNER_UP_BUTTON:
     case NS_THEME_SPINNER_DOWN_BUTTON:
       aResult->width++;
       aResult->height = aResult->height / 2 + 1;
@@ -2211,26 +2212,26 @@ nsNativeThemeWin::WidgetStateChanged(nsI
       aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
       aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
       aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
-  if (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION &&
+  if (!nsUXThemeData::sIsVistaOrLater &&
       (aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL || 
       aWidgetType == NS_THEME_SCROLLBAR_TRACK_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 (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
+  if (nsUXThemeData::sIsVistaOrLater &&
       (aWidgetType == NS_THEME_DROPDOWN || aWidgetType == NS_THEME_DROPDOWN_BUTTON) &&
       IsHTMLContent(aFrame))
   {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // XXXdwh Not sure what can really be done here.  Can at least guess for
@@ -2343,22 +2344,22 @@ nsNativeThemeWin::GetWidgetTransparency(
   }
 
   PRInt32 part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   // Fail conservatively
   NS_ENSURE_SUCCESS(rv, eUnknownTransparency);
 
   if (part <= 0) {
-    // Not a real part code, so IsThemeBackgroundPartiallyTransparent may
+    // Not a real part code, so isThemeBackgroundPartiallyTransparent may
     // not work, so don't call it.
     return eUnknownTransparency;
   }
 
-  if (IsThemeBackgroundPartiallyTransparent(theme, part, state))
+  if (nsUXThemeData::isThemeBackgroundPartiallyTransparent(theme, part, state))
     return eTransparent;
   return eOpaque;
 }
 
 /* Windows 9x/NT/2000/Classic XP Theme Support */
 
 bool 
 nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext,
--- a/widget/windows/nsUXThemeConstants.h
+++ b/widget/windows/nsUXThemeConstants.h
@@ -179,16 +179,24 @@
 #define MPI_NORMAL 1
 #define MPI_HOT 2
 #define MPI_DISABLED 3
 #define MPI_DISABLEDHOT 4
 
 #define MSM_NORMAL 1
 #define MSM_DISABLED 2
 
+// Theme size constants
+// minimum size
+#define TS_MIN 0
+// size without stretching
+#define TS_TRUE 1
+// size that theme mgr will use to draw part
+#define TS_DRAW 2
+
 // From tmschema.h in the Vista SDK
 #define TMT_TEXTCOLOR 3803
 #define TMT_SIZINGMARGINS 3601
 #define TMT_CONTENTMARGINS 3602
 #define TMT_CAPTIONMARGINS 3603
 
 // Rebar constants
 #define RP_BAND              3
--- a/widget/windows/nsUXThemeData.cpp
+++ b/widget/windows/nsUXThemeData.cpp
@@ -62,23 +62,42 @@ nsUXThemeData::sThemes[eUXNumClasses];
 
 HMODULE
 nsUXThemeData::sThemeDLL = NULL;
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
 HMODULE
 nsUXThemeData::sDwmDLL = NULL;
 #endif
 
+BOOL
+nsUXThemeData::sFlatMenus = FALSE;
 bool
-nsUXThemeData::sFlatMenus = false;
+nsUXThemeData::sIsXPOrLater = false;
+bool
+nsUXThemeData::sIsVistaOrLater = false;
 
 bool nsUXThemeData::sTitlebarInfoPopulatedAero = false;
 bool nsUXThemeData::sTitlebarInfoPopulatedThemed = false;
 SIZE nsUXThemeData::sCommandButtons[4];
 
+nsUXThemeData::OpenThemeDataPtr nsUXThemeData::openTheme = NULL;
+nsUXThemeData::CloseThemeDataPtr nsUXThemeData::closeTheme = NULL;
+nsUXThemeData::DrawThemeBackgroundPtr nsUXThemeData::drawThemeBG = NULL;
+nsUXThemeData::DrawThemeEdgePtr nsUXThemeData::drawThemeEdge = NULL;
+nsUXThemeData::GetThemeContentRectPtr nsUXThemeData::getThemeContentRect = NULL;
+nsUXThemeData::GetThemeBackgroundRegionPtr nsUXThemeData::getThemeBackgroundRegion = NULL;
+nsUXThemeData::GetThemePartSizePtr nsUXThemeData::getThemePartSize = NULL;
+nsUXThemeData::GetThemeSysFontPtr nsUXThemeData::getThemeSysFont = NULL;
+nsUXThemeData::GetThemeColorPtr nsUXThemeData::getThemeColor = NULL;
+nsUXThemeData::GetThemeMarginsPtr nsUXThemeData::getThemeMargins = NULL;
+nsUXThemeData::IsAppThemedPtr nsUXThemeData::isAppThemed = NULL;
+nsUXThemeData::GetCurrentThemeNamePtr nsUXThemeData::getCurrentThemeName = NULL;
+nsUXThemeData::GetThemeSysColorPtr nsUXThemeData::getThemeSysColor = NULL;
+nsUXThemeData::IsThemeBackgroundPartiallyTransparentPtr nsUXThemeData::isThemeBackgroundPartiallyTransparent = NULL;
+
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
 nsUXThemeData::DwmExtendFrameIntoClientAreaProc nsUXThemeData::dwmExtendFrameIntoClientAreaPtr = NULL;
 nsUXThemeData::DwmIsCompositionEnabledProc nsUXThemeData::dwmIsCompositionEnabledPtr = NULL;
 nsUXThemeData::DwmSetIconicThumbnailProc nsUXThemeData::dwmSetIconicThumbnailPtr = NULL;
 nsUXThemeData::DwmSetIconicLivePreviewBitmapProc nsUXThemeData::dwmSetIconicLivePreviewBitmapPtr = NULL;
 nsUXThemeData::DwmGetWindowAttributeProc nsUXThemeData::dwmGetWindowAttributePtr = NULL;
 nsUXThemeData::DwmSetWindowAttributeProc nsUXThemeData::dwmSetWindowAttributePtr = NULL;
 nsUXThemeData::DwmInvalidateIconicBitmapsProc nsUXThemeData::dwmInvalidateIconicBitmapsPtr = NULL;
@@ -97,16 +116,36 @@ nsUXThemeData::Teardown() {
 }
 
 void
 nsUXThemeData::Initialize()
 {
   ::ZeroMemory(sThemes, sizeof(sThemes));
   NS_ASSERTION(!sThemeDLL, "nsUXThemeData being initialized twice!");
 
+  WinUtils::WinVersion version = WinUtils::GetWindowsVersion();
+  sIsXPOrLater = version >= WinUtils::WINXP_VERSION;
+  sIsVistaOrLater = version >= WinUtils::VISTA_VERSION;
+
+  if (GetThemeDLL()) {
+    openTheme = (OpenThemeDataPtr)GetProcAddress(sThemeDLL, "OpenThemeData");
+    closeTheme = (CloseThemeDataPtr)GetProcAddress(sThemeDLL, "CloseThemeData");
+    drawThemeBG = (DrawThemeBackgroundPtr)GetProcAddress(sThemeDLL, "DrawThemeBackground");
+    drawThemeEdge = (DrawThemeEdgePtr)GetProcAddress(sThemeDLL, "DrawThemeEdge");
+    getThemeContentRect = (GetThemeContentRectPtr)GetProcAddress(sThemeDLL, "GetThemeBackgroundContentRect");
+    getThemeBackgroundRegion = (GetThemeBackgroundRegionPtr)GetProcAddress(sThemeDLL, "GetThemeBackgroundRegion");
+    getThemePartSize = (GetThemePartSizePtr)GetProcAddress(sThemeDLL, "GetThemePartSize");
+    getThemeSysFont = (GetThemeSysFontPtr)GetProcAddress(sThemeDLL, "GetThemeSysFont");
+    getThemeColor = (GetThemeColorPtr)GetProcAddress(sThemeDLL, "GetThemeColor");
+    getThemeMargins = (GetThemeMarginsPtr)GetProcAddress(sThemeDLL, "GetThemeMargins");
+    isAppThemed = (IsAppThemedPtr)GetProcAddress(sThemeDLL, "IsAppThemed");
+    getCurrentThemeName = (GetCurrentThemeNamePtr)GetProcAddress(sThemeDLL, "GetCurrentThemeName");
+    getThemeSysColor = (GetThemeSysColorPtr)GetProcAddress(sThemeDLL, "GetThemeSysColor");
+    isThemeBackgroundPartiallyTransparent = (IsThemeBackgroundPartiallyTransparentPtr)GetProcAddress(sThemeDLL, "IsThemeBackgroundPartiallyTransparent");
+  }
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
   if (GetDwmDLL()) {
     dwmExtendFrameIntoClientAreaPtr = (DwmExtendFrameIntoClientAreaProc)::GetProcAddress(sDwmDLL, "DwmExtendFrameIntoClientArea");
     dwmIsCompositionEnabledPtr = (DwmIsCompositionEnabledProc)::GetProcAddress(sDwmDLL, "DwmIsCompositionEnabled");
     dwmSetIconicThumbnailPtr = (DwmSetIconicThumbnailProc)::GetProcAddress(sDwmDLL, "DwmSetIconicThumbnail");
     dwmSetIconicLivePreviewBitmapPtr = (DwmSetIconicLivePreviewBitmapProc)::GetProcAddress(sDwmDLL, "DwmSetIconicLivePreviewBitmap");
     dwmGetWindowAttributePtr = (DwmGetWindowAttributeProc)::GetProcAddress(sDwmDLL, "DwmGetWindowAttribute");
     dwmSetWindowAttributePtr = (DwmSetWindowAttributeProc)::GetProcAddress(sDwmDLL, "DwmSetWindowAttribute");
@@ -118,46 +157,56 @@ nsUXThemeData::Initialize()
 
   Invalidate();
 }
 
 void
 nsUXThemeData::Invalidate() {
   for(int i = 0; i < eUXNumClasses; i++) {
     if(sThemes[i]) {
-      CloseThemeData(sThemes[i]);
+      closeTheme(sThemes[i]);
       sThemes[i] = NULL;
     }
   }
-  BOOL useFlat = false;
-  sFlatMenus = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &useFlat, 0) ?
-                   useFlat : false;
+  if (sIsXPOrLater) {
+    BOOL useFlat = false;
+    sFlatMenus = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &useFlat, 0) ?
+                     useFlat : false;
+  } else {
+    // Contrary to Microsoft's documentation, SPI_GETFLATMENU will not fail
+    // on Windows 2000, and it is also possible (though unlikely) for WIN2K
+    // to be misconfigured in such a way that it would return true, so we
+    // shall give WIN2K special treatment
+    sFlatMenus = false;
+  }
 }
 
 HANDLE
 nsUXThemeData::GetTheme(nsUXThemeClass cls) {
   NS_ASSERTION(cls < eUXNumClasses, "Invalid theme class!");
+  if(!sThemeDLL)
+    return NULL;
   if(!sThemes[cls])
   {
-    sThemes[cls] = OpenThemeData(NULL, GetClassName(cls));
+    sThemes[cls] = openTheme(NULL, GetClassName(cls));
   }
   return sThemes[cls];
 }
 
 HMODULE
 nsUXThemeData::GetThemeDLL() {
-  if (!sThemeDLL)
+  if (!sThemeDLL && sIsXPOrLater)
     sThemeDLL = ::LoadLibraryW(kThemeLibraryName);
   return sThemeDLL;
 }
 
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
 HMODULE
 nsUXThemeData::GetDwmDLL() {
-  if (!sDwmDLL && WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION)
+  if (!sDwmDLL && sIsVistaOrLater)
     sDwmDLL = ::LoadLibraryW(kDwmLibraryName);
   return sDwmDLL;
 }
 #endif
 
 const wchar_t *nsUXThemeData::GetClassName(nsUXThemeClass cls) {
   switch(cls) {
     case eUXButton:
@@ -353,24 +402,24 @@ nsUXThemeData::UpdateNativeThemeInfo()
 {
   // Trigger a refresh of themed button metrics if needed
   sTitlebarInfoPopulatedThemed =
     (WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION);
 
   sIsDefaultWindowsTheme = false;
   sThemeId = LookAndFeel::eWindowsTheme_Generic;
 
-  if (!IsAppThemed()) {
+  if (!IsAppThemed() || !getCurrentThemeName) {
     sThemeId = LookAndFeel::eWindowsTheme_Classic;
     return;
   }
 
   WCHAR themeFileName[MAX_PATH + 1];
   WCHAR themeColor[MAX_PATH + 1];
-  if (FAILED(GetCurrentThemeName(themeFileName,
+  if (FAILED(getCurrentThemeName(themeFileName,
                                  MAX_PATH,
                                  themeColor,
                                  MAX_PATH,
                                  NULL, 0))) {
     sThemeId = LookAndFeel::eWindowsTheme_Classic;
     return;
   }
 
--- a/widget/windows/nsUXThemeData.h
+++ b/widget/windows/nsUXThemeData.h
@@ -122,17 +122,19 @@ class nsUXThemeData {
   
   static const wchar_t *GetClassName(nsUXThemeClass);
 
 public:
   static const PRUnichar kThemeLibraryName[];
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
    static const PRUnichar kDwmLibraryName[];
 #endif
-  static bool sFlatMenus;
+  static BOOL sFlatMenus;
+  static bool sIsXPOrLater;
+  static bool sIsVistaOrLater;
   static bool sTitlebarInfoPopulatedAero;
   static bool sTitlebarInfoPopulatedThemed;
   static SIZE sCommandButtons[4];
   static mozilla::LookAndFeel::WindowsTheme sThemeId;
   static bool sIsDefaultWindowsTheme;
 
   static void Initialize();
   static void Teardown();
@@ -146,16 +148,74 @@ public:
   // nsWindow calls this to update desktop settings info
   static void InitTitlebarInfo();
   static void UpdateTitlebarInfo(HWND aWnd);
 
   static void UpdateNativeThemeInfo();
   static mozilla::LookAndFeel::WindowsTheme GetNativeThemeId();
   static bool IsDefaultWindowTheme();
 
+  static inline BOOL IsAppThemed() {
+    return isAppThemed && isAppThemed();
+  }
+
+  static inline HRESULT GetThemeColor(nsUXThemeClass cls, int iPartId, int iStateId,
+                                                   int iPropId, OUT COLORREF* pFont) {
+    if(!getThemeColor)
+      return E_FAIL;
+    return getThemeColor(GetTheme(cls), iPartId, iStateId, iPropId, pFont);
+  }
+
+  // UXTheme.dll Function typedefs and declarations
+  typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
+  typedef HRESULT (WINAPI*CloseThemeDataPtr)(HANDLE hTheme);
+  typedef HRESULT (WINAPI*DrawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId, 
+                                            int iStateId, const RECT *pRect,
+                                            const RECT* pClipRect);
+  typedef HRESULT (WINAPI*DrawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId, 
+                                            int iStateId, const RECT *pDestRect,
+                                            uint uEdge, uint uFlags,
+                                            const RECT* pContentRect);
+  typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+                                            int iStateId, const RECT* pRect,
+                                            RECT* pContentRect);
+  typedef HRESULT (WINAPI*GetThemeBackgroundRegionPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+                                            int iStateId, const RECT* pRect,
+                                            HRGN *pRegion);
+  typedef HRESULT (WINAPI*GetThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
+                                         int iStateId, RECT* prc, int ts,
+                                         SIZE* psz);
+  typedef HRESULT (WINAPI*GetThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
+  typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, int iPartId,
+                                     int iStateId, int iPropId, OUT COLORREF* pFont);
+  typedef HRESULT (WINAPI*GetThemeMarginsPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+                                           int iStateid, int iPropId,
+                                           LPRECT prc, MARGINS *pMargins);
+  typedef BOOL (WINAPI*IsAppThemedPtr)(VOID);
+  typedef HRESULT (WINAPI*GetCurrentThemeNamePtr)(LPWSTR pszThemeFileName, int dwMaxNameChars,
+                                                  LPWSTR pszColorBuff, int cchMaxColorChars,
+                                                  LPWSTR pszSizeBuff, int cchMaxSizeChars);
+  typedef COLORREF (WINAPI*GetThemeSysColorPtr)(HANDLE hTheme, int iColorID);
+  typedef BOOL (WINAPI*IsThemeBackgroundPartiallyTransparentPtr)(HANDLE hTheme, int iPartId, int iStateId);
+
+  static OpenThemeDataPtr openTheme;
+  static CloseThemeDataPtr closeTheme;
+  static DrawThemeBackgroundPtr drawThemeBG;
+  static DrawThemeEdgePtr drawThemeEdge;
+  static GetThemeContentRectPtr getThemeContentRect;
+  static GetThemeBackgroundRegionPtr getThemeBackgroundRegion;
+  static GetThemePartSizePtr getThemePartSize;
+  static GetThemeSysFontPtr getThemeSysFont;
+  static GetThemeColorPtr getThemeColor;
+  static GetThemeMarginsPtr getThemeMargins;
+  static IsAppThemedPtr isAppThemed;
+  static GetCurrentThemeNamePtr getCurrentThemeName;
+  static GetThemeSysColorPtr getThemeSysColor;
+  static IsThemeBackgroundPartiallyTransparentPtr isThemeBackgroundPartiallyTransparent;
+
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
   // dwmapi.dll function typedefs and declarations
   typedef HRESULT (WINAPI*DwmExtendFrameIntoClientAreaProc)(HWND hWnd, const MARGINS *pMarInset);
   typedef HRESULT (WINAPI*DwmIsCompositionEnabledProc)(BOOL *pfEnabled);
   typedef HRESULT (WINAPI*DwmSetIconicThumbnailProc)(HWND hWnd, HBITMAP hBitmap, DWORD dwSITFlags);
   typedef HRESULT (WINAPI*DwmSetIconicLivePreviewBitmapProc)(HWND hWnd, HBITMAP hBitmap, POINT *pptClient, DWORD dwSITFlags);
   typedef HRESULT (WINAPI*DwmGetWindowAttributeProc)(HWND hWnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
   typedef HRESULT (WINAPI*DwmSetWindowAttributeProc)(HWND hWnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -108,17 +108,16 @@
 #include "mozilla/Util.h"
 
 #include "nsWindow.h"
 
 #include <windows.h>
 #include <process.h>
 #include <commctrl.h>
 #include <unknwn.h>
-#include <psapi.h>
 
 #include "prlog.h"
 #include "prtime.h"
 #include "prprf.h"
 #include "prmem.h"
 
 #include "mozilla/WidgetTraceEvent.h"
 #include "nsIAppShell.h"
@@ -1269,40 +1268,38 @@ NS_METHOD nsWindow::IsVisible(bool & bSt
  * window clipping regions for window transparency.
  *
  **************************************************************/
 
 // 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.
 void nsWindow::ClearThemeRegion()
 {
-  if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-      !HasGlass() &&
+  if (nsUXThemeData::sIsVistaOrLater && !HasGlass() &&
       (mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
        (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
     SetWindowRgn(mWnd, NULL, false);
   }
 }
 
 void nsWindow::SetThemeRegion()
 {
   // Popup types that have a visual styles region applied (bug 376408). This can be expanded
   // for other window types as needed. The regions are applied generically to the base window
   // 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 (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION &&
-      !HasGlass() &&
+  if (nsUXThemeData::sIsVistaOrLater && !HasGlass() &&
       (mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
        (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
     HRGN hRgn = nsnull;
     RECT rect = {0,0,mBounds.width,mBounds.height};
     
     HDC dc = ::GetDC(mWnd);
-    GetThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip), dc, TTP_STANDARD, TS_NORMAL, &rect, &hRgn);
+    nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip), dc, TTP_STANDARD, TS_NORMAL, &rect, &hRgn);
     if (hRgn) {
       if (!SetWindowRgn(mWnd, hRgn, false)) // do not delete or alter hRgn if accepted.
         DeleteObject(hRgn);
     }
     ::ReleaseDC(mWnd, dc);
   }
 }
 
@@ -6355,17 +6352,17 @@ nsWindow::InitMouseWheelScrollData()
     // sMouseWheelScrollLines should explicitly equal WHEEL_PAGESCROLL, but
     // since some mouse drivers use an arbitrary large number instead,
     // we have to handle that as well.
     sMouseWheelScrollLines = WHEEL_PAGESCROLL;
   }
 
   if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
                               &sMouseWheelScrollChars, 0)) {
-    NS_ASSERTION(WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION,
+    NS_ASSERTION(!nsUXThemeData::sIsVistaOrLater,
                  "Failed to get SPI_GETWHEELSCROLLCHARS");
     sMouseWheelScrollChars = 1;
   } else if (sMouseWheelScrollChars > WHEEL_DELTA) {
     // See the comments for the case sMouseWheelScrollLines > WHEEL_DELTA.
     sMouseWheelScrollChars = WHEEL_PAGESCROLL;
   }
 
   sEnablePixelScrolling =
@@ -7456,34 +7453,44 @@ bool nsWindow::OnResize(nsIntRect &aWind
   return false;
 }
 
 bool nsWindow::OnHotKey(WPARAM wParam, LPARAM lParam)
 {
   return true;
 }
 
+typedef DWORD (WINAPI *GetProcessImageFileNameProc)(HANDLE, LPWSTR, DWORD);
+
 // Determine whether the given HWND is the handle for the Elantech helper
 // window.  The helper window cannot be distinguished based on its
 // window class, so we need to check if it is owned by the helper process,
 // ETDCtrl.exe.
 static bool IsElantechHelperWindow(HWND aHWND)
 {
+  static HMODULE hPSAPI = ::LoadLibraryW(L"psapi.dll");
+  static GetProcessImageFileNameProc pGetProcessImageFileName =
+    reinterpret_cast<GetProcessImageFileNameProc>(::GetProcAddress(hPSAPI, "GetProcessImageFileNameW"));
+
+  if (!pGetProcessImageFileName) {
+    return false;
+  }
+
   const PRUnichar* filenameSuffix = L"\\etdctrl.exe";
   const int filenameSuffixLength = 12;
 
   DWORD pid;
   ::GetWindowThreadProcessId(aHWND, &pid);
 
   bool result = false;
 
   HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
   if (hProcess) {
     PRUnichar path[256] = {L'\0'};
-    if (GetProcessImageFileName(hProcess, path, ArrayLength(path))) {
+    if (pGetProcessImageFileName(hProcess, path, ArrayLength(path))) {
       int pathLength = lstrlenW(path);
       if (pathLength >= filenameSuffixLength) {
         if (lstrcmpiW(path + pathLength - filenameSuffixLength, filenameSuffix) == 0) {
           result = true;
         }
       }
     }
     ::CloseHandle(hProcess);
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -753,19 +753,33 @@ PRUint8* nsWindowGfx::Data32BitTo1Bit(PR
         mask = 0x80;
       }
     }
   }
 
   return outData;
 }
 
+bool nsWindowGfx::IsCursorTranslucencySupported()
+{
+  static bool didCheck = false;
+  static bool isSupported = false;
+  if (!didCheck) {
+    didCheck = true;
+    // Cursor translucency is supported on Windows XP and newer
+    isSupported = WinUtils::GetWindowsVersion() >= WinUtils::WINXP_VERSION;
+  }
+
+  return isSupported;
+}
+
 /**
  * Convert the given image data to a HBITMAP. If the requested depth is
- * 32 bit, a bitmap with an alpha channel will be returned.
+ * 32 bit and the OS supports translucency, a bitmap with an alpha channel
+ * will be returned.
  *
  * @param aImageData The image data to convert. Must use the format accepted
  *                   by CreateDIBitmap.
  * @param aWidth     With of the bitmap, in pixels.
  * @param aHeight    Height of the image, in pixels.
  * @param aDepth     Image depth, in bits. Should be one of 1, 24 and 32.
  *
  * @return The HBITMAP representing the image. Caller should call
@@ -774,17 +788,17 @@ PRUint8* nsWindowGfx::Data32BitTo1Bit(PR
  */
 HBITMAP nsWindowGfx::DataToBitmap(PRUint8* aImageData,
                                   PRUint32 aWidth,
                                   PRUint32 aHeight,
                                   PRUint32 aDepth)
 {
   HDC dc = ::GetDC(NULL);
 
-  if (aDepth == 32) {
+  if (aDepth == 32 && IsCursorTranslucencySupported()) {
     // Alpha channel. We need the new header.
     BITMAPV4HEADER head = { 0 };
     head.bV4Size = sizeof(head);
     head.bV4Width = aWidth;
     head.bV4Height = aHeight;
     head.bV4Planes = 1;
     head.bV4BitCount = aDepth;
     head.bV4V4Compression = BI_BITFIELDS;
--- a/widget/windows/nsWindowGfx.h
+++ b/widget/windows/nsWindowGfx.h
@@ -67,12 +67,13 @@ public:
   static gfxIntSize GetIconMetrics(IconSizeType aSizeType);
   static nsresult CreateIcon(imgIContainer *aContainer, bool aIsCursor, PRUint32 aHotspotX, PRUint32 aHotspotY, gfxIntSize aScaledSize, HICON *aIcon);
 
 private:
   /**
    * Cursor helpers
    */
   static PRUint8*         Data32BitTo1Bit(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
+  static bool             IsCursorTranslucencySupported();
   static HBITMAP          DataToBitmap(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
 };
 
 #endif // WindowGfx_h__
--- a/widget/xpwidgets/GfxDriverInfo.h
+++ b/widget/xpwidgets/GfxDriverInfo.h
@@ -49,16 +49,17 @@
 #define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion) \
     mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion))
 
 namespace mozilla {
 namespace widget {
 
 enum OperatingSystem {
   DRIVER_OS_UNKNOWN = 0,
+  DRIVER_OS_WINDOWS_2000,
   DRIVER_OS_WINDOWS_XP,
   DRIVER_OS_WINDOWS_SERVER_2003,
   DRIVER_OS_WINDOWS_VISTA,
   DRIVER_OS_WINDOWS_7,
   DRIVER_OS_LINUX,
   DRIVER_OS_OS_X_10_5,
   DRIVER_OS_OS_X_10_6,
   DRIVER_OS_OS_X_10_7,
--- a/widget/xpwidgets/GfxInfoBase.cpp
+++ b/widget/xpwidgets/GfxInfoBase.cpp
@@ -282,17 +282,19 @@ BlacklistNodeToTextValue(nsIDOMNode *aBl
   aValue = value;
 
   return true;
 }
 
 static OperatingSystem
 BlacklistOSToOperatingSystem(const nsAString& os)
 {
-  if (os == NS_LITERAL_STRING("WINNT 5.1"))
+  if (os == NS_LITERAL_STRING("WINNT 5.0"))
+    return DRIVER_OS_WINDOWS_2000;
+  else if (os == NS_LITERAL_STRING("WINNT 5.1"))
     return DRIVER_OS_WINDOWS_XP;
   else if (os == NS_LITERAL_STRING("WINNT 5.2"))
     return DRIVER_OS_WINDOWS_SERVER_2003;
   else if (os == NS_LITERAL_STRING("WINNT 6.0"))
     return DRIVER_OS_WINDOWS_VISTA;
   else if (os == NS_LITERAL_STRING("WINNT 6.1"))
     return DRIVER_OS_WINDOWS_7;
   else if (os == NS_LITERAL_STRING("Linux"))
--- a/xpcom/base/nsSetDllDirectory.h
+++ b/xpcom/base/nsSetDllDirectory.h
@@ -65,11 +65,27 @@ static void SanitizeEnvironmentVariables
         }
         delete[] newPath;
       }
     }
     delete[] originalPath;
   }
 }
 
+// Sets the directory from which DLLs can be loaded if the SetDllDirectory OS
+// API is available.
+// You must call SanitizeEnvironmentVariables before this function when calling
+// it the first time.
+static inline void NS_SetDllDirectory(const WCHAR *aDllDirectory)
+{
+  typedef BOOL
+  (WINAPI *pfnSetDllDirectory) (LPCWSTR);
+  pfnSetDllDirectory setDllDirectory = nsnull;
+  setDllDirectory = reinterpret_cast<pfnSetDllDirectory>
+      (GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDllDirectoryW"));
+  if (setDllDirectory) {
+    setDllDirectory(aDllDirectory);
+  }
+}
+
 }
 
 #endif
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -200,57 +200,237 @@ StackWalkInitCriticalAddress()
 #include "nscore.h"
 #include <windows.h>
 #include <process.h>
 #include <stdio.h>
 #include "plstr.h"
 #include "mozilla/FunctionTimer.h"
 
 #include "nspr.h"
+#if defined(_M_IX86) || defined(_M_AMD64)
 #include <imagehlp.h>
 // We need a way to know if we are building for WXP (or later), as if we are, we
 // need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill.
 // A value of 9 indicates we want to use the new APIs.
-#if API_VERSION_NUMBER < 9
-#error Too old imagehlp.h
+#if API_VERSION_NUMBER >= 9
+#define USING_WXP_VERSION 1
+#endif
 #endif
 
 using namespace mozilla;
 
 // Define these as static pointers so that we can load the DLL on the
 // fly (and not introduce a link-time dependency on it). Tip o' the
 // hat to Matt Pietrick for this idea. See:
 //
 //   http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
 //
 PR_BEGIN_EXTERN_C
 
+typedef DWORD (__stdcall *SYMSETOPTIONSPROC)(DWORD);
+extern SYMSETOPTIONSPROC _SymSetOptions;
+
+typedef BOOL (__stdcall *SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
+extern SYMINITIALIZEPROC _SymInitialize;
+
+typedef BOOL (__stdcall *SYMCLEANUPPROC)(HANDLE);
+extern SYMCLEANUPPROC _SymCleanup;
+
+typedef BOOL (__stdcall *STACKWALKPROC)(DWORD,
+                                        HANDLE,
+                                        HANDLE,
+                                        LPSTACKFRAME,
+                                        LPVOID,
+                                        PREAD_PROCESS_MEMORY_ROUTINE,
+                                        PFUNCTION_TABLE_ACCESS_ROUTINE,
+                                        PGET_MODULE_BASE_ROUTINE,
+                                        PTRANSLATE_ADDRESS_ROUTINE);
+extern  STACKWALKPROC _StackWalk;
+
+#ifdef USING_WXP_VERSION
+typedef BOOL (__stdcall *STACKWALKPROC64)(DWORD,
+                                          HANDLE,
+                                          HANDLE,
+                                          LPSTACKFRAME64,
+                                          PVOID,
+                                          PREAD_PROCESS_MEMORY_ROUTINE64,
+                                          PFUNCTION_TABLE_ACCESS_ROUTINE64,
+                                          PGET_MODULE_BASE_ROUTINE64,
+                                          PTRANSLATE_ADDRESS_ROUTINE64);
+extern  STACKWALKPROC64 _StackWalk64;
+#endif
+
+typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
+extern  SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+
+#ifdef USING_WXP_VERSION
+typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC64)(HANDLE, DWORD64);
+extern  SYMFUNCTIONTABLEACCESSPROC64 _SymFunctionTableAccess64;
+#endif
+
+typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
+extern  SYMGETMODULEBASEPROC _SymGetModuleBase;
+
+#ifdef USING_WXP_VERSION
+typedef DWORD64 (__stdcall *SYMGETMODULEBASEPROC64)(HANDLE, DWORD64);
+extern  SYMGETMODULEBASEPROC64 _SymGetModuleBase64;
+#endif
+
+typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
+extern  SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+
+#ifdef USING_WXP_VERSION
+typedef BOOL (__stdcall *SYMFROMADDRPROC)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
+extern  SYMFROMADDRPROC _SymFromAddr;
+#endif
+
+typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD);
+extern  SYMLOADMODULE _SymLoadModule;
+
+#ifdef USING_WXP_VERSION
+typedef DWORD ( __stdcall *SYMLOADMODULE64)(HANDLE, HANDLE, PCSTR, PCSTR, DWORD64, DWORD);
+extern  SYMLOADMODULE64 _SymLoadModule64;
+#endif
+
+typedef DWORD ( __stdcall *SYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
+extern  SYMUNDNAME _SymUnDName;
+
+typedef DWORD ( __stdcall *SYMGETMODULEINFO)( HANDLE, DWORD, PIMAGEHLP_MODULE);
+extern  SYMGETMODULEINFO _SymGetModuleInfo;
+
+#ifdef USING_WXP_VERSION
+typedef BOOL ( __stdcall *SYMGETMODULEINFO64)( HANDLE, DWORD64, PIMAGEHLP_MODULE64);
+extern  SYMGETMODULEINFO64 _SymGetModuleInfo64;
+#endif
+
+typedef BOOL ( __stdcall *ENUMLOADEDMODULES)( HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
+extern  ENUMLOADEDMODULES _EnumerateLoadedModules;
+
+#ifdef USING_WXP_VERSION
+typedef BOOL ( __stdcall *ENUMLOADEDMODULES64)( HANDLE, PENUMLOADED_MODULES_CALLBACK64, PVOID);
+extern  ENUMLOADEDMODULES64 _EnumerateLoadedModules64;
+#endif
+
+typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE);
+extern  SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+
+#ifdef USING_WXP_VERSION
+typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64);
+extern  SYMGETLINEFROMADDRPROC64 _SymGetLineFromAddr64;
+#endif
+
 extern HANDLE hStackWalkMutex; 
 
 bool EnsureSymInitialized();
 
 bool EnsureImageHlpInitialized();
 
+/*
+ * SymGetModuleInfoEspecial
+ *
+ * Attempt to determine the module information.
+ * Bug 112196 says this DLL may not have been loaded at the time
+ *  SymInitialize was called, and thus the module information
+ *  and symbol information is not available.
+ * This code rectifies that problem.
+ * Line information is optional.
+ */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo);
+
 struct WalkStackData {
   PRUint32 skipFrames;
   HANDLE thread;
   bool walkCallingThread;
   HANDLE process;
   HANDLE eventStart;
   HANDLE eventEnd;
   void **pcs;
   PRUint32 pc_size;
   PRUint32 pc_count;
 };
 
 void PrintError(char *prefix, WalkStackData* data);
 unsigned int WINAPI WalkStackThread(void* data);
 void WalkStackMain64(struct WalkStackData* data);
+#if !defined(_WIN64)
+void WalkStackMain(struct WalkStackData* data);
+#endif
 
 
+// Define these as static pointers so that we can load the DLL on the
+// fly (and not introduce a link-time dependency on it). Tip o' the
+// hat to Matt Pietrick for this idea. See:
+//
+//   http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
+//
+
+SYMSETOPTIONSPROC _SymSetOptions;
+
+SYMINITIALIZEPROC _SymInitialize;
+
+SYMCLEANUPPROC _SymCleanup;
+
+STACKWALKPROC _StackWalk;
+#ifdef USING_WXP_VERSION
+STACKWALKPROC64 _StackWalk64;
+#else
+#define _StackWalk64 0
+#endif
+
+SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+#ifdef USING_WXP_VERSION
+SYMFUNCTIONTABLEACCESSPROC64 _SymFunctionTableAccess64;
+#else
+#define _SymFunctionTableAccess64 0
+#endif
+
+SYMGETMODULEBASEPROC _SymGetModuleBase;
+#ifdef USING_WXP_VERSION
+SYMGETMODULEBASEPROC64 _SymGetModuleBase64;
+#else
+#define _SymGetModuleBase64 0
+#endif
+
+SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+#ifdef USING_WXP_VERSION
+SYMFROMADDRPROC _SymFromAddr;
+#else
+#define _SymFromAddr 0
+#endif
+
+SYMLOADMODULE _SymLoadModule;
+#ifdef USING_WXP_VERSION
+SYMLOADMODULE64 _SymLoadModule64;
+#else
+#define _SymLoadModule64 0
+#endif
+
+SYMUNDNAME _SymUnDName;
+
+SYMGETMODULEINFO _SymGetModuleInfo;
+#ifdef USING_WXP_VERSION
+SYMGETMODULEINFO64 _SymGetModuleInfo64;
+#else
+#define _SymGetModuleInfo64 0
+#endif
+
+ENUMLOADEDMODULES _EnumerateLoadedModules;
+#ifdef USING_WXP_VERSION
+ENUMLOADEDMODULES64 _EnumerateLoadedModules64;
+#else
+#define _EnumerateLoadedModules64 0
+#endif
+
+SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+#ifdef USING_WXP_VERSION
+SYMGETLINEFROMADDRPROC64 _SymGetLineFromAddr64;
+#else
+#define _SymGetLineFromAddr64 0
+#endif
+
 DWORD gStackWalkThread;
 CRITICAL_SECTION gDbgHelpCS;
 
 PR_END_EXTERN_C
 
 // Routine to print an error message to standard error.
 // Will also call callback with error, if data supplied.
 void PrintError(char *prefix)
@@ -299,22 +479,89 @@ EnsureImageHlpInitialized()
     ::CloseHandle(hStackWalkThread);
 
     // Wait for the thread's event loop to start before posting events to it.
     ::WaitForSingleObject(readyEvent, INFINITE);
     ::CloseHandle(readyEvent);
 
     ::InitializeCriticalSection(&gDbgHelpCS);
 
+    HMODULE module = ::LoadLibraryW(L"DBGHELP.DLL");
+    if (!module) {
+        module = ::LoadLibraryW(L"IMAGEHLP.DLL");
+        if (!module) return false;
+    }
+
+    _SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions");
+    if (!_SymSetOptions) return false;
+
+    _SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize");
+    if (!_SymInitialize) return false;
+
+    _SymCleanup = (SYMCLEANUPPROC)GetProcAddress(module, "SymCleanup");
+    if (!_SymCleanup) return false;
+
+#ifdef USING_WXP_VERSION
+    _StackWalk64 = (STACKWALKPROC64)GetProcAddress(module, "StackWalk64");
+#endif
+    _StackWalk = (STACKWALKPROC)GetProcAddress(module, "StackWalk");
+    if (!_StackWalk64  && !_StackWalk) return false;
+
+#ifdef USING_WXP_VERSION
+    _SymFunctionTableAccess64 = (SYMFUNCTIONTABLEACCESSPROC64) GetProcAddress(module, "SymFunctionTableAccess64");
+#endif
+    _SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(module, "SymFunctionTableAccess");
+    if (!_SymFunctionTableAccess64 && !_SymFunctionTableAccess) return false;
+
+#ifdef USING_WXP_VERSION
+    _SymGetModuleBase64 = (SYMGETMODULEBASEPROC64)GetProcAddress(module, "SymGetModuleBase64");
+#endif
+    _SymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(module, "SymGetModuleBase");
+    if (!_SymGetModuleBase64 && !_SymGetModuleBase) return false;
+
+    _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr");
+#ifdef USING_WXP_VERSION
+    _SymFromAddr = (SYMFROMADDRPROC)GetProcAddress(module, "SymFromAddr");
+#endif
+    if (!_SymFromAddr && !_SymGetSymFromAddr) return false;
+
+#ifdef USING_WXP_VERSION
+    _SymLoadModule64 = (SYMLOADMODULE64)GetProcAddress(module, "SymLoadModule64");
+#endif
+    _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule");
+    if (!_SymLoadModule64 && !_SymLoadModule) return false;
+
+    _SymUnDName = (SYMUNDNAME)GetProcAddress(module, "SymUnDName");
+    if (!_SymUnDName) return false;
+
+#ifdef USING_WXP_VERSION
+    _SymGetModuleInfo64 = (SYMGETMODULEINFO64)GetProcAddress(module, "SymGetModuleInfo64");
+#endif
+    _SymGetModuleInfo = (SYMGETMODULEINFO)GetProcAddress(module, "SymGetModuleInfo");
+    if (!_SymGetModuleInfo64 && !_SymGetModuleInfo) return false;
+
+#ifdef USING_WXP_VERSION
+    _EnumerateLoadedModules64 = (ENUMLOADEDMODULES64)GetProcAddress(module, "EnumerateLoadedModules64");
+#endif
+    _EnumerateLoadedModules = (ENUMLOADEDMODULES)GetProcAddress(module, "EnumerateLoadedModules");
+    if (!_EnumerateLoadedModules64 && !_EnumerateLoadedModules) return false;
+
+#ifdef USING_WXP_VERSION
+    _SymGetLineFromAddr64 = (SYMGETLINEFROMADDRPROC64)GetProcAddress(module, "SymGetLineFromAddr64");
+#endif
+    _SymGetLineFromAddr = (SYMGETLINEFROMADDRPROC)GetProcAddress(module, "SymGetLineFromAddr");
+    if (!_SymGetLineFromAddr64 && !_SymGetLineFromAddr) return false;
+
     return gInitialized = true;
 }
 
 void
 WalkStackMain64(struct WalkStackData* data)
 {
+#ifdef USING_WXP_VERSION
     // Get the context information for the thread. That way we will
     // know where our sp, fp, pc, etc. are and can fill in the
     // STACKFRAME64 with the initial values.
     CONTEXT context;
     HANDLE myProcess = data->process;
     HANDLE myThread = data->thread;
     DWORD64 addr;
     STACKFRAME64 frame64;
@@ -352,33 +599,33 @@ WalkStackMain64(struct WalkStackData* da
     frame64.AddrFrame.Mode   = AddrModeFlat;
     frame64.AddrReturn.Mode  = AddrModeFlat;
 
     // Now walk the stack
     while (1) {
 
         // debug routines are not threadsafe, so grab the lock.
         EnterCriticalSection(&gDbgHelpCS);
-        ok = StackWalk64(
+        ok = _StackWalk64(
 #ifdef _M_AMD64
           IMAGE_FILE_MACHINE_AMD64,
 #elif defined _M_IA64
           IMAGE_FILE_MACHINE_IA64,
 #elif defined _M_IX86
           IMAGE_FILE_MACHINE_I386,
 #else
 #error "Should not have compiled this code"
 #endif
           myProcess,
           myThread,
           &frame64,
           &context,
           NULL,
-          SymFunctionTableAccess64, // function table access routine
-          SymGetModuleBase64,       // module base routine
+          _SymFunctionTableAccess64, // function table access routine
+          _SymGetModuleBase64,       // module base routine
           0
         );
         LeaveCriticalSection(&gDbgHelpCS);
 
         if (ok)
             addr = frame64.AddrPC.Offset;
         else {
             addr = 0;
@@ -396,19 +643,116 @@ WalkStackMain64(struct WalkStackData* da
         if (data->pc_count < data->pc_size)
             data->pcs[data->pc_count] = (void*)addr;
         ++data->pc_count;
 
         if (frame64.AddrReturn.Offset == 0)
             break;
     }
     return;
+#endif
 }
 
 
+#if !defined(_WIN64)
+void
+WalkStackMain(struct WalkStackData* data)
+{
+    // Get the context information for the thread. That way we will
+    // know where our sp, fp, pc, etc. are and can fill in the
+    // STACKFRAME with the initial values.
+    CONTEXT context;
+    HANDLE myProcess = data->process;
+    HANDLE myThread = data->thread;
+    DWORD addr;
+    STACKFRAME frame;
+    int skip = data->skipFrames; // skip our own stack walking frames
+    BOOL ok;
+
+    // Get a context for the specified thread.
+    memset(&context, 0, sizeof(CONTEXT));
+    context.ContextFlags = CONTEXT_FULL;
+    if (!GetThreadContext(myThread, &context)) {
+        PrintError("GetThreadContext");
+        return;
+    }
+
+    // Setup initial stack frame to walk from
+#if defined _M_IX86
+    memset(&frame, 0, sizeof(frame));
+    frame.AddrPC.Offset    = context.Eip;
+    frame.AddrPC.Mode      = AddrModeFlat;
+    frame.AddrStack.Offset = context.Esp;
+    frame.AddrStack.Mode   = AddrModeFlat;
+    frame.AddrFrame.Offset = context.Ebp;
+    frame.AddrFrame.Mode   = AddrModeFlat;
+#else
+    PrintError("Unknown platform. No stack walking.");
+    return;
+#endif
+
+    // Now walk the stack
+    while (1) {
+
+        // debug routines are not threadsafe, so grab the lock.
+        EnterCriticalSection(&gDbgHelpCS);
+        ok = _StackWalk(
+            IMAGE_FILE_MACHINE_I386,
+            myProcess,
+            myThread,
+            &frame,
+            &context,
+            0,                        // read process memory routine
+            _SymFunctionTableAccess,  // function table access routine
+            _SymGetModuleBase,        // module base routine
+            0                         // translate address routine
+          );
+        LeaveCriticalSection(&gDbgHelpCS);
+
+        if (ok)
+            addr = frame.AddrPC.Offset;
+        else {
+            addr = 0;
+            PrintError("WalkStack");
+        }
+
+        if (!ok || (addr == 0)) {
+            break;
+        }
+
+        if (skip-- > 0) {
+            continue;
+        }
+
+        if (data->pc_count < data->pc_size)
+            data->pcs[data->pc_count] = (void*)addr;
+        ++data->pc_count;
+
+        if (frame.AddrReturn.Offset == 0)
+            break;
+    }
+
+    return;
+
+}
+#endif
+
+static
+void PerformStackWalk(struct WalkStackData* data)
+{
+#if defined(_WIN64)
+    WalkStackMain64(data);
+#else
+    if (_StackWalk64)
+        WalkStackMain64(data);
+    else
+        WalkStackMain(data);
+#endif
+}
+
 unsigned int WINAPI
 WalkStackThread(void* aData)
 {
     BOOL msgRet;
     MSG msg;
 
     // Call PeekMessage to force creation of a message queue so that
     // other threads can safely post events to us.
@@ -436,17 +780,17 @@ WalkStackThread(void* aData)
 
             // Suspend the calling thread, dump his stack, and then resume him.
             // He's currently waiting for us to finish so now should be a good time.
             ret = ::SuspendThread( data->thread );
             if (ret == -1) {
                 PrintError("ThreadSuspend");
             }
             else {
-                WalkStackMain64(data);
+                PerformStackWalk(data);
 
                 ret = ::ResumeThread(data->thread);
                 if (ret == -1) {
                     PrintError("ThreadResume");
                 }
             }
 
             ::SetEvent(data->eventEnd);
@@ -510,17 +854,17 @@ NS_StackWalk(NS_WalkStackCallback aCallb
     void *local_pcs[1024];
     data.pcs = local_pcs;
     data.pc_count = 0;
     data.pc_size = ArrayLength(local_pcs);
 
     if (aThread) {
         // If we're walking the stack of another thread, we don't need to
         // use a separate walker thread.
-        WalkStackMain64(&data);
+        PerformStackWalk(&data);
     } else {
         data.eventStart = ::CreateEvent(NULL, FALSE /* auto-reset*/,
                               FALSE /* initially non-signaled */, NULL);
         data.eventEnd = ::CreateEvent(NULL, FALSE /* auto-reset*/,
                             FALSE /* initially non-signaled */, NULL);
 
         ::PostThreadMessage(gStackWalkThread, WM_USER, 0, (LPARAM)&data);
 
@@ -551,22 +895,54 @@ NS_StackWalk(NS_WalkStackCallback aCallb
 
     if (data.pc_size > ArrayLength(local_pcs))
         free(data.pcs);
 
     return NS_OK;
 }
 
 
+static BOOL CALLBACK callbackEspecial(
+  PCSTR aModuleName,
+  ULONG aModuleBase,
+  ULONG aModuleSize,
+  PVOID aUserContext)
+{
+    BOOL retval = TRUE;
+    DWORD addr = *(DWORD*)aUserContext;
+
+    /*
+     * You'll want to control this if we are running on an
+     *  architecture where the addresses go the other direction.
+     * Not sure this is even a realistic consideration.
+     */
+    const BOOL addressIncreases = TRUE;
+
+    /*
+     * If it falls inside the known range, load the symbols.
+     */
+    if (addressIncreases
+       ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize))
+       : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))
+        ) {
+        retval = _SymLoadModule(GetCurrentProcess(), NULL, (PSTR)aModuleName, NULL, aModuleBase, aModuleSize);
+        if (!retval)
+            PrintError("SymLoadModule");
+    }
+
+    return retval;
+}
+
 static BOOL CALLBACK callbackEspecial64(
   PCSTR aModuleName,
   DWORD64 aModuleBase,
   ULONG aModuleSize,
   PVOID aUserContext)
 {
+#ifdef USING_WXP_VERSION
     BOOL retval = TRUE;
     DWORD64 addr = *(DWORD64*)aUserContext;
 
     /*
      * You'll want to control this if we are running on an
      *  architecture where the addresses go the other direction.
      * Not sure this is even a realistic consideration.
      */
@@ -574,130 +950,190 @@ static BOOL CALLBACK callbackEspecial64(
 
     /*
      * If it falls in side the known range, load the symbols.
      */
     if (addressIncreases
        ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize))
        : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))
         ) {
-        retval = SymLoadModule64(GetCurrentProcess(), NULL, (PSTR)aModuleName, NULL, aModuleBase, aModuleSize);
+        retval = _SymLoadModule64(GetCurrentProcess(), NULL, (PSTR)aModuleName, NULL, aModuleBase, aModuleSize);
         if (!retval)
             PrintError("SymLoadModule64");
     }
 
     return retval;
+#else
+    return FALSE;
+#endif
 }
 
 /*
  * SymGetModuleInfoEspecial
  *
  * Attempt to determine the module information.
  * Bug 112196 says this DLL may not have been loaded at the time
  *  SymInitialize was called, and thus the module information
  *  and symbol information is not available.
  * This code rectifies that problem.
  */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo)
+{
+    BOOL retval = FALSE;
+
+    /*
+     * Init the vars if we have em.
+     */
+    aModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE);
+    if (nsnull != aLineInfo) {
+      aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE);
+    }
+
+    /*
+     * Give it a go.
+     * It may already be loaded.
+     */
+    retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+
+    if (FALSE == retval) {
+        BOOL enumRes = FALSE;
+
+        /*
+         * Not loaded, here's the magic.
+         * Go through all the modules.
+         */
+        // Need to cast to PENUMLOADED_MODULES_CALLBACK because the
+        // constness of the first parameter of
+        // PENUMLOADED_MODULES_CALLBACK varies over SDK versions (from
+        // non-const to const over time).  See bug 391848 and bug
+        // 415426.
+        enumRes = _EnumerateLoadedModules(aProcess, (PENUMLOADED_MODULES_CALLBACK)callbackEspecial, (PVOID)&aAddr);
+        if (FALSE != enumRes)
+        {
+            /*
+             * One final go.
+             * If it fails, then well, we have other problems.
+             */
+            retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+            if (!retval)
+                PrintError("SymGetModuleInfo");
+        }
+    }
+
+    /*
+     * If we got module info, we may attempt line info as well.
+     * We will not report failure if this does not work.
+     */
+    if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr) {
+        DWORD displacement = 0;
+        BOOL lineRes = FALSE;
+        lineRes = _SymGetLineFromAddr(aProcess, aAddr, &displacement, aLineInfo);
+    }
+
+    return retval;
+}
 
 // New members were added to IMAGEHLP_MODULE64 (that show up in the
 // Platform SDK that ships with VC8, but not the Platform SDK that ships
 // with VC7.1, i.e., between DbgHelp 6.0 and 6.1), but we don't need to
 // use them, and it's useful to be able to function correctly with the
 // older library.  (Stock Windows XP SP2 seems to ship with dbghelp.dll
 // version 5.1.)  Since Platform SDK version need not correspond to
 // compiler version, and the version number in debughlp.h was NOT bumped
 // when these changes were made, ifdef based on a constant that was
 // added between these versions.
 #ifdef SSRVOPT_SETCONTEXT
 #define NS_IMAGEHLP_MODULE64_SIZE (((offsetof(IMAGEHLP_MODULE64, LoadedPdbName) + sizeof(DWORD64) - 1) / sizeof(DWORD64)) * sizeof(DWORD64))
 #else
 #define NS_IMAGEHLP_MODULE64_SIZE sizeof(IMAGEHLP_MODULE64)
 #endif
 
+#ifdef USING_WXP_VERSION
 BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, PIMAGEHLP_MODULE64 aModuleInfo, PIMAGEHLP_LINE64 aLineInfo)
 {
     BOOL retval = FALSE;
 
     /*
      * Init the vars if we have em.
      */
     aModuleInfo->SizeOfStruct = NS_IMAGEHLP_MODULE64_SIZE;
     if (nsnull != aLineInfo) {
         aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
     }
 
     /*
      * Give it a go.
      * It may already be loaded.
      */
-    retval = SymGetModuleInfo64(aProcess, aAddr, aModuleInfo);
+    retval = _SymGetModuleInfo64(aProcess, aAddr, aModuleInfo);
 
     if (FALSE == retval) {
         BOOL enumRes = FALSE;
 
         /*
          * Not loaded, here's the magic.
          * Go through all the modules.
          */
         // Need to cast to PENUMLOADED_MODULES_CALLBACK64 because the
         // constness of the first parameter of
         // PENUMLOADED_MODULES_CALLBACK64 varies over SDK versions (from
         // non-const to const over time).  See bug 391848 and bug
         // 415426.
-        enumRes = EnumerateLoadedModules64(aProcess, (PENUMLOADED_MODULES_CALLBACK64)callbackEspecial64, (PVOID)&aAddr);
+        enumRes = _EnumerateLoadedModules64(aProcess, (PENUMLOADED_MODULES_CALLBACK64)callbackEspecial64, (PVOID)&aAddr);
         if (FALSE != enumRes)
         {
             /*
              * One final go.
              * If it fails, then well, we have other problems.
              */
-            retval = SymGetModuleInfo64(aProcess, aAddr, aModuleInfo);
+            retval = _SymGetModuleInfo64(aProcess, aAddr, aModuleInfo);
             if (!retval)
                 PrintError("SymGetModuleInfo64");
         }
     }
 
     /*
      * If we got module info, we may attempt line info as well.
      * We will not report failure if this does not work.
      */
-    if (FALSE != retval && nsnull != aLineInfo) {
+    if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr64) {
         DWORD displacement = 0;
         BOOL lineRes = FALSE;
-        lineRes = SymGetLineFromAddr64(aProcess, aAddr, &displacement, aLineInfo);
+        lineRes = _SymGetLineFromAddr64(aProcess, aAddr, &displacement, aLineInfo);
         if (!lineRes) {
             // Clear out aLineInfo to indicate that it's not valid
             memset(aLineInfo, 0, sizeof(*aLineInfo));
         }
     }
 
     return retval;
 }
+#endif
 
 bool
 EnsureSymInitialized()
 {
     static bool gInitialized = false;
     bool retStat;
 
     if (gInitialized)
         return gInitialized;
 
     NS_TIME_FUNCTION;
 
     if (!EnsureImageHlpInitialized())
         return false;
 
-    SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
-    retStat = SymInitialize(GetCurrentProcess(), NULL, TRUE);
+    _SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+    retStat = _SymInitialize(GetCurrentProcess(), NULL, TRUE);
     if (!retStat)
         PrintError("SymInitialize");
 
     gInitialized = retStat;
-    /* XXX At some point we need to arrange to call SymCleanup */
+    /* XXX At some point we need to arrange to call _SymCleanup */
 
     return retStat;
 }
 
 
 EXPORT_XPCOM_API(nsresult)
 NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
 {
@@ -712,68 +1148,134 @@ NS_DescribeCodeAddress(void *aPC, nsCode
         return NS_ERROR_FAILURE;
 
     HANDLE myProcess = ::GetCurrentProcess();
     BOOL ok;
 
     // debug routines are not threadsafe, so grab the lock.
     EnterCriticalSection(&gDbgHelpCS);
 
-    //
-    // Attempt to load module info before we attempt to resolve the symbol.
-    // This just makes sure we get good info if available.
-    //
+#ifdef USING_WXP_VERSION
+    if (_StackWalk64) {
+        //
+        // Attempt to load module info before we attempt to resolve the symbol.
+        // This just makes sure we get good info if available.
+        //
+
+        DWORD64 addr = (DWORD64)aPC;
+        IMAGEHLP_MODULE64 modInfo;
+        IMAGEHLP_LINE64 lineInfo;
+        BOOL modInfoRes;
+        modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo);
+
+        if (modInfoRes) {
+            PL_strncpyz(aDetails->library, modInfo.ModuleName,
+                        sizeof(aDetails->library));
+            aDetails->loffset = (char*) aPC - (char*) modInfo.BaseOfImage;
+            
+            if (lineInfo.FileName) {
+                PL_strncpyz(aDetails->filename, lineInfo.FileName,
+                            sizeof(aDetails->filename));
+                aDetails->lineno = lineInfo.LineNumber;
+            }
+        }
 
-    DWORD64 addr = (DWORD64)aPC;
-    IMAGEHLP_MODULE64 modInfo;
-    IMAGEHLP_LINE64 lineInfo;
-    BOOL modInfoRes;
-    modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo);
+        ULONG64 buffer[(sizeof(SYMBOL_INFO) +
+          MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
+        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+        pSymbol->MaxNameLen = MAX_SYM_NAME;
+
+        DWORD64 displacement;
+        ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
 
-    if (modInfoRes) {
-        PL_strncpyz(aDetails->library, modInfo.ModuleName,
-                    sizeof(aDetails->library));
-        aDetails->loffset = (char*) aPC - (char*) modInfo.BaseOfImage;
-        
-        if (lineInfo.FileName) {
+        if (ok) {
+            PL_strncpyz(aDetails->function, pSymbol->Name,
+                        sizeof(aDetails->function));
+            aDetails->foffset = displacement;
+        }
+    } else
+#endif
+    {
+        //
+        // Attempt to load module info before we attempt to resolve the symbol.
+        // This just makes sure we get good info if available.
+        //
+
+        DWORD_PTR addr = (DWORD_PTR)aPC;
+        IMAGEHLP_MODULE modInfo;
+        IMAGEHLP_LINE lineInfo;
+        BOOL modInfoRes;
+        modInfoRes = SymGetModuleInfoEspecial(myProcess, addr, &modInfo, &lineInfo);
+
+        if (modInfoRes) {
+            PL_strncpyz(aDetails->library, modInfo.ModuleName,
+                        sizeof(aDetails->library));
+            aDetails->loffset = (char*) aPC - (char*) modInfo.BaseOfImage;
             PL_strncpyz(aDetails->filename, lineInfo.FileName,
                         sizeof(aDetails->filename));
             aDetails->lineno = lineInfo.LineNumber;
         }
-    }
 
-    ULONG64 buffer[(sizeof(SYMBOL_INFO) +
-      MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
-    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
-    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
-    pSymbol->MaxNameLen = MAX_SYM_NAME;
+#ifdef USING_WXP_VERSION
+        ULONG64 buffer[(sizeof(SYMBOL_INFO) +
+          MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
+        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+        pSymbol->MaxNameLen = MAX_SYM_NAME;
+
+        DWORD64 displacement;
 
-    DWORD64 displacement;
-    ok = SymFromAddr(myProcess, addr, &displacement, pSymbol);
+        ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
+#else
+        char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
+        PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) buf;
+        pSymbol->SizeOfStruct = sizeof(buf);
+        pSymbol->MaxNameLength = 512;
+
+        DWORD displacement;
 
-    if (ok) {
-        PL_strncpyz(aDetails->function, pSymbol->Name,
-                    sizeof(aDetails->function));
-        aDetails->foffset = displacement;
+        ok = _SymGetSymFromAddr(myProcess,
+                    frame.AddrPC.Offset,
+                    &displacement,
+                    pSymbol);
+#endif
+
+        if (ok) {
+            PL_strncpyz(aDetails->function, pSymbol->Name,
+                        sizeof(aDetails->function));
+            aDetails->foffset = displacement;
+        }
     }
 
     LeaveCriticalSection(&gDbgHelpCS); // release our lock
     return NS_OK;
 }
 
 EXPORT_XPCOM_API(nsresult)
 NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
                             char *aBuffer, PRUint32 aBufferSize)
 {
-    if (aDetails->function[0])
-        _snprintf(aBuffer, aBufferSize, "%s!%s+0x%016lX",
-                  aDetails->library, aDetails->function, aDetails->foffset);
-    else
-        _snprintf(aBuffer, aBufferSize, "0x%016lX", aPC);
-
+#ifdef USING_WXP_VERSION
+    if (_StackWalk64) {
+        if (aDetails->function[0])
+            _snprintf(aBuffer, aBufferSize, "%s!%s+0x%016lX",
+                      aDetails->library, aDetails->function, aDetails->foffset);
+        else
+            _snprintf(aBuffer, aBufferSize, "0x%016lX", aPC);
+    } else {
+#endif
+        if (aDetails->function[0])
+            _snprintf(aBuffer, aBufferSize, "%s!%s+0x%08lX",
+                      aDetails->library, aDetails->function, aDetails->foffset);
+        else
+            _snprintf(aBuffer, aBufferSize, "0x%08lX", aPC);
+#ifdef USING_WXP_VERSION
+    }
+#endif
     aBuffer[aBufferSize - 1] = '\0';
 
     PRUint32 len = strlen(aBuffer);
     if (aDetails->filename[0]) {
         _snprintf(aBuffer + len, aBufferSize - len, " (%s, line %d)\n",
                   aDetails->filename, aDetails->lineno);
     } else {
         aBuffer[len] = '\n';
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -668,17 +668,17 @@ GetSpecialSystemDirectory(SystemDirector
         }
 
         case Win_Downloads:
         {
             // Defined in KnownFolders.h.
             GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64,
                                        0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
             nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
-            // On WinXP, there is no downloads folder, default
+            // On WinXP and 2k, there is no downloads folder, default
             // to 'Desktop'.
             if(NS_ERROR_FAILURE == rv)
             {
               rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
             }
             return rv;
         }
 
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -105,16 +105,19 @@ unsigned char *_mbsstr( const unsigned c
 #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000
 #endif
 
 #ifndef DRIVE_REMOTE
 #define DRIVE_REMOTE 4
 #endif
 
+ILCreateFromPathWPtr nsLocalFile::sILCreateFromPathW = NULL;
+SHOpenFolderAndSelectItemsPtr nsLocalFile::sSHOpenFolderAndSelectItems = NULL;
+
 class nsDriveEnumerator : public nsISimpleEnumerator
 {
 public:
     nsDriveEnumerator();
     virtual ~nsDriveEnumerator();
     NS_DECL_ISUPPORTS
     NS_DECL_NSISIMPLEENUMERATOR
     nsresult Init();
@@ -2708,16 +2711,29 @@ nsLocalFile::SetPersistentDescriptor(con
 {
     if (IsUTF8(aPersistentDescriptor))
         return InitWithPath(NS_ConvertUTF8toUTF16(aPersistentDescriptor));
     else
         return InitWithNativePath(aPersistentDescriptor);
 }   
 
 /* attrib unsigned long fileAttributesWin; */
+static bool IsXPOrGreater()
+{
+    OSVERSIONINFO osvi;
+
+    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    GetVersionEx(&osvi);
+
+    return ((osvi.dwMajorVersion > 5) ||
+       ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1)));
+}
+
 NS_IMETHODIMP
 nsLocalFile::GetFileAttributesWin(PRUint32 *aAttribs)
 {
     *aAttribs = 0;
     DWORD dwAttrs = GetFileAttributesW(mWorkingPath.get());
     if (dwAttrs == INVALID_FILE_ATTRIBUTES)
       return NS_ERROR_FILE_INVALID_PATH;
 
@@ -2729,79 +2745,133 @@ nsLocalFile::GetFileAttributesWin(PRUint
     
 NS_IMETHODIMP
 nsLocalFile::SetFileAttributesWin(PRUint32 aAttribs)
 {
     DWORD dwAttrs = GetFileAttributesW(mWorkingPath.get());
     if (dwAttrs == INVALID_FILE_ATTRIBUTES)
       return NS_ERROR_FILE_INVALID_PATH;
 
-    if (aAttribs & WFA_SEARCH_INDEXED) {
-        dwAttrs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
-    } else {
-        dwAttrs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+    if (IsXPOrGreater()) {
+      if (aAttribs & WFA_SEARCH_INDEXED) {
+          dwAttrs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+      } else {
+          dwAttrs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+      }
     }
 
     if (SetFileAttributesW(mWorkingPath.get(), dwAttrs) == 0)
       return NS_ERROR_FAILURE;
     return NS_OK;
-}
+}   
 
 
 NS_IMETHODIMP
 nsLocalFile::Reveal()
 {
-  // make sure mResolvedPath is set
-  bool isDirectory = false;
+    // make sure mResolvedPath is set
+    nsresult rv = ResolveAndStat();
+    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+        return rv;
+
+    // First try revealing with the shell, and if that fails fall back
+    // to the classic way using explorer.exe command line parameters
+    rv = RevealUsingShell();
+    if (NS_FAILED(rv)) {
+      rv = RevealClassic();
+    }
+
+    return rv;
+}
+
+nsresult
+nsLocalFile::RevealClassic()
+{
+  // use the full path to explorer for security
+  nsCOMPtr<nsILocalFile> winDir;
+  nsresult rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(winDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoString explorerPath;
+  rv = winDir->GetPath(explorerPath);  
+  NS_ENSURE_SUCCESS(rv, rv);
+  explorerPath.AppendLiteral("\\explorer.exe");
+
+  // Always open a new window for files because Win2K doesn't appear to select
+  // the file if a window showing that folder was already open. If the resolved 
+  // path is a directory then instead of opening the parent and selecting it, 
+  // we open the directory itself.
+  nsAutoString explorerParams;
+  if (mFileInfo64.type != PR_FILE_DIRECTORY) // valid because we ResolveAndStat above
+    explorerParams.AppendLiteral("/n,/select,");
+  explorerParams.Append(L'\"');
+  explorerParams.Append(mResolvedPath);
+  explorerParams.Append(L'\"');
+
+  if (::ShellExecuteW(NULL, L"open", explorerPath.get(), explorerParams.get(),
+    NULL, SW_SHOWNORMAL) <= (HINSTANCE) 32)
+    return NS_ERROR_FAILURE;
+
+  return NS_OK;
+}
+
+nsresult 
+nsLocalFile::RevealUsingShell()
+{
+  // All of these shell32.dll related pointers should be non NULL 
+  // on XP and later.
+  if (!sILCreateFromPathW || !sSHOpenFolderAndSelectItems) {
+    return NS_ERROR_FAILURE;
+  }
+
+  bool isDirectory;
   nsresult rv = IsDirectory(&isDirectory);
-  if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
-      return rv;
+  NS_ENSURE_SUCCESS(rv, rv);
 
   HRESULT hr;
   if (isDirectory) {
     // We have a directory so we should open the directory itself.
-    ITEMIDLIST *dir = ILCreateFromPathW(mResolvedPath.get());
+    ITEMIDLIST *dir = sILCreateFromPathW(mResolvedPath.get());
     if (!dir) {
       return NS_ERROR_FAILURE;
     }
 
     const ITEMIDLIST* selection[] = { dir };
     UINT count = ArrayLength(selection);
 
     //Perform the open of the directory.
-    hr = SHOpenFolderAndSelectItems(dir, count, selection, 0);
+    hr = sSHOpenFolderAndSelectItems(dir, count, selection, 0);
     CoTaskMemFree(dir);
   }
   else {
     // Obtain the parent path of the item we are revealing.
     nsCOMPtr<nsIFile> parentDirectory;
     rv = GetParent(getter_AddRefs(parentDirectory));
     NS_ENSURE_SUCCESS(rv, rv);
     nsAutoString parentDirectoryPath;
     rv = parentDirectory->GetPath(parentDirectoryPath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // We have a file so we should open the parent directory.
-    ITEMIDLIST *dir = ILCreateFromPathW(parentDirectoryPath.get());
+    ITEMIDLIST *dir = sILCreateFromPathW(parentDirectoryPath.get());
     if (!dir) {
       return NS_ERROR_FAILURE;
     }
 
     // Set the item in the directory to select to the file we want to reveal.
-    ITEMIDLIST *item = ILCreateFromPathW(mResolvedPath.get());
+    ITEMIDLIST *item = sILCreateFromPathW(mResolvedPath.get());
     if (!item) {
       CoTaskMemFree(dir);
       return NS_ERROR_FAILURE;
     }
     
     const ITEMIDLIST* selection[] = { item };
     UINT count = ArrayLength(selection);
 
     //Perform the selection of the file.
-    hr = SHOpenFolderAndSelectItems(dir, count, selection, 0);
+    hr = sSHOpenFolderAndSelectItems(dir, count, selection, 0);
 
     CoTaskMemFree(dir);
     CoTaskMemFree(item);
   }
   
   if (SUCCEEDED(hr)) {
     return NS_OK;
   }
@@ -3100,16 +3170,31 @@ nsLocalFile::GetHashCode(PRUint32 *aResu
 // nsLocalFile <static members>
 //-----------------------------------------------------------------------------
 
 void
 nsLocalFile::GlobalInit()
 {
     nsresult rv = NS_CreateShortcutResolver();
     NS_ASSERTION(NS_SUCCEEDED(rv), "Shortcut resolver could not be created");
+
+    // shell32.dll should be loaded already, so we are not actually 
+    // loading the library here.
+    HMODULE hLibShell = GetModuleHandleW(L"shell32.dll");
+    if (hLibShell) {
+      // ILCreateFromPathW is available in XP and up.
+      sILCreateFromPathW = (ILCreateFromPathWPtr) 
+                            GetProcAddress(hLibShell, 
+                                           "ILCreateFromPathW");
+
+      // SHOpenFolderAndSelectItems is available in XP and up.
+      sSHOpenFolderAndSelectItems = (SHOpenFolderAndSelectItemsPtr) 
+                                     GetProcAddress(hLibShell, 
+                                                    "SHOpenFolderAndSelectItems");
+    }
 }
 
 void
 nsLocalFile::GlobalShutdown()
 {
     NS_DestroyShortcutResolver();
 }
 
--- a/xpcom/io/nsLocalFileWin.h
+++ b/xpcom/io/nsLocalFileWin.h
@@ -51,16 +51,21 @@
 #include "nsIHashable.h"
 #include "nsIClassInfoImpl.h"
 
 #include "windows.h"
 #include "shlobj.h"
 
 #include <sys/stat.h>
 
+typedef LPITEMIDLIST (WINAPI *ILCreateFromPathWPtr)(PCWSTR);
+typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsPtr)(PCIDLIST_ABSOLUTE, UINT, 
+                                                        PCUITEMID_CHILD_ARRAY,
+                                                        DWORD);
+
 class nsLocalFile : public nsILocalFileWin,
                     public nsIHashable
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
     
     nsLocalFile();
 
@@ -118,11 +123,16 @@ private:
                             const nsAString &newName,
                             bool followSymlinks, bool move,
                             bool skipNtfsAclReset = false);
 
     nsresult SetModDate(PRInt64 aLastModifiedTime, const PRUnichar *filePath);
     nsresult HasFileAttribute(DWORD fileAttrib, bool *_retval);
     nsresult AppendInternal(const nsAFlatString &node,
                             bool multipleComponents);
+    nsresult RevealClassic(); // Reveals the path using explorer.exe cmdline
+    nsresult RevealUsingShell(); // Uses newer shell API to reveal the path
+
+    static ILCreateFromPathWPtr sILCreateFromPathW;
+    static SHOpenFolderAndSelectItemsPtr sSHOpenFolderAndSelectItems;
 };
 
 #endif
--- a/xpcom/threads/nsProcess.h
+++ b/xpcom/threads/nsProcess.h
@@ -98,15 +98,16 @@ private:
   PRInt32 mPid;
   nsCOMPtr<nsIObserver> mObserver;
   nsWeakPtr mWeakObserver;
 
   // These members are modified by multiple threads, any accesses should be
   // protected with mLock.
   PRInt32 mExitValue;
 #if defined(PROCESSMODEL_WINAPI)
+  typedef DWORD (WINAPI*GetProcessIdPtr)(HANDLE process);
   HANDLE mProcess;
 #elif !defined(XP_MACOSX)
   PRProcess *mProcess;
 #endif
 };
 
 #endif
--- a/xpcom/threads/nsProcessCommon.cpp
+++ b/xpcom/threads/nsProcessCommon.cpp
@@ -495,17 +495,23 @@ nsProcess::RunProcess(bool blocking, cha
     }
 
     mProcess = sinfo.hProcess;
 
     PR_Free(wideFile);
     if (cmdLine)
         PR_Free(cmdLine);
 
-    mPid = GetProcessId(mProcess);
+    HMODULE kernelDLL = ::LoadLibraryW(L"kernel32.dll");
+    if (kernelDLL) {
+        GetProcessIdPtr getProcessId = (GetProcessIdPtr)GetProcAddress(kernelDLL, "GetProcessId");
+        if (getProcessId)
+            mPid = getProcessId(mProcess);
+        FreeLibrary(kernelDLL);
+    }
 #elif defined(XP_MACOSX)
     // Initialize spawn attributes.
     posix_spawnattr_t spawnattr;
     if (posix_spawnattr_init(&spawnattr) != 0) {
         return NS_ERROR_FAILURE;
     }
 
     // Set spawn attributes.