Backout f1acc52a59da (bug 719983) & 6771bd53e267 (bug 699247) for 30% WinXp Ts regression

This commit is contained in:
Ed Morley 2012-02-08 21:04:21 +00:00
parent 945463763f
commit ada565efab
37 changed files with 1548 additions and 345 deletions

View File

@ -353,6 +353,16 @@ nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
}
#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;

View File

@ -57,6 +57,7 @@
#include "nsString.h"
#include "nsILocalFile.h"
#include "nsUnicharUtils.h"
#include "nsSetDllDirectory.h"
using namespace mozilla;
@ -302,7 +303,7 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
}
if (protectCurrentDirectory) {
SetDllDirectory(NULL);
mozilla::NS_SetDllDirectory(NULL);
}
nsresult rv = plugin->Load(outLibrary);
@ -310,7 +311,7 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
*outLibrary = NULL;
if (protectCurrentDirectory) {
SetDllDirectory(L"");
mozilla::NS_SetDllDirectory(L"");
}
if (restoreOrigDir) {

View File

@ -147,7 +147,7 @@ PluginProcessChild::Init()
}
if (protectCurrentDirectory) {
SanitizeEnvironmentVariables();
SetDllDirectory(L"");
NS_SetDllDirectory(L"");
}
#else

View File

@ -107,14 +107,33 @@ static const char *MapErrorCode(int rc)
//-----------------------------------------------------------------------------
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;

View File

@ -81,6 +81,18 @@ GetCairoAntialiasOption(gfxFont::AntialiasOption anAntialiasOption)
#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()
{
@ -88,6 +100,10 @@ UsingClearType()
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0) ||
!fontSmoothing)
{
return false;
}
if (!HasClearType()) {
return false;
}

View File

@ -65,7 +65,6 @@
#include "mozilla/Telemetry.h"
#include <usp10.h>
#include <t2embapi.h>
using namespace mozilla;
@ -103,6 +102,50 @@ BuildKeyNameFromFontName(nsAString &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)
@ -114,7 +157,7 @@ public:
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];
@ -551,6 +594,8 @@ GDIFontFamily::FindStyleVariations()
gfxGDIFontList::gfxGDIFontList()
{
mFontSubstitutes.Init(50);
InitializeFontEmbeddingProcs();
}
static void
@ -737,6 +782,15 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
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 {
@ -840,6 +894,10 @@ gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
};
FontDataDeleter autoDelete(aFontData);
// if calls aren't available, bail
if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
return nsnull;
bool hasVertical;
bool isCFF = gfxFontUtils::IsCffFont(aFontData, hasVertical);
@ -878,11 +936,11 @@ gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
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];

View File

@ -223,6 +223,7 @@ public:
// based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
enum {
kWindowsUnknown = 0,
kWindows2000 = 0x50000,
kWindowsXP = 0x50001,
kWindowsServer2003 = 0x50002,
kWindowsVista = 0x60000,

View File

@ -165,7 +165,7 @@ EnableBatteryNotifications()
} 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) {

View File

@ -74,7 +74,7 @@ main(int argc, char* argv[])
// the details.
if (proctype != GeckoProcessType_Plugin) {
mozilla::SanitizeEnvironmentVariables();
SetDllDirectory(L"");
mozilla::NS_SetDllDirectory(L"");
}
#endif

View File

@ -79,6 +79,9 @@ nsAutodial::nsAutodial()
mNumRASConnectionEntries(0),
mAutodialServiceDialingLocation(-1)
{
mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
GetVersionEx(&mOSVerInfo);
// Initializations that can be made again since RAS OS settings can
// change.
Init();
@ -429,27 +432,22 @@ nsresult nsAutodial::GetDefaultEntryName(PRUnichar* entryName, int bufferSize)
//
// 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);
if (result != ERROR_SUCCESS)
// Windows 2000
if ((mOSVerInfo.dwMajorVersion == 5) && (mOSVerInfo.dwMinorVersion == 0)) // Windows 2000
{
// If not present, try HKLM.
key = L"RemoteAccess";
val = L"InternetProfile";
result = ::RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
HKEY_CURRENT_USER,
key,
0,
KEY_READ,
@ -460,6 +458,36 @@ nsresult nsAutodial::GetDefaultEntryName(PRUnichar* entryName, int bufferSize)
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;

View File

@ -126,6 +126,9 @@ private:
// 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

View File

@ -960,8 +960,18 @@ nsSocketTransportService::DiscoverMaxCount()
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

View File

@ -653,6 +653,8 @@ nsHttpHandler::BuildUserAgent()
}
#ifdef XP_WIN
typedef BOOL (WINAPI *IsWow64ProcessP) (HANDLE, PBOOL);
#define WNT_BASE "Windows NT %ld.%ld"
#define W64_PREFIX "; Win64"
#endif
@ -715,7 +717,10 @@ nsHttpHandler::InitUserAgentComponents()
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

View File

@ -59,11 +59,42 @@
#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) {
@ -77,6 +108,18 @@ static void InitNetshellLibrary(void)
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);
@ -95,6 +138,8 @@ nsNotifyAddrListener::nsNotifyAddrListener()
, mCheckAttempted(false)
, mShutdownEvent(nsnull)
{
mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
GetVersionEx(&mOSVerInfo);
}
nsNotifyAddrListener::~nsNotifyAddrListener()
@ -142,10 +187,17 @@ nsNotifyAddrListener::Run()
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);
@ -184,6 +236,11 @@ nsNotifyAddrListener::Init(void)
//
// 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)
@ -257,6 +314,125 @@ nsNotifyAddrListener::ChangeEvent::Run()
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)
{
@ -371,19 +547,22 @@ nsNotifyAddrListener::CheckAdaptersAddresses(void)
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) {
@ -416,6 +595,10 @@ nsNotifyAddrListener::CheckLinkStatus(void)
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

View File

@ -81,6 +81,9 @@ protected:
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);
@ -88,6 +91,7 @@ protected:
nsCOMPtr<nsIThread> mThread;
OSVERSIONINFO mOSVerInfo;
HANDLE mShutdownEvent;
};

View File

@ -527,7 +527,10 @@ 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
@ -538,14 +541,10 @@ 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

View File

@ -77,7 +77,7 @@ 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

View File

@ -247,6 +247,13 @@ nsMIMEInfoWin::GetProperty(const nsAString& aName, nsIVariant* *_retval)
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
@ -267,6 +274,15 @@ nsMIMEInfoWin::LoadUriInternal(nsIURI * aURL)
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));
@ -281,14 +297,22 @@ nsMIMEInfoWin::LoadUriInternal(nsIURI * aURL)
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);
@ -297,6 +321,8 @@ nsMIMEInfoWin::LoadUriInternal(nsIURI * aURL)
}
if (pidl)
CoTaskMemFree(pidl);
if (hDll)
::FreeLibrary(hDll);
}
return rv;

View File

@ -272,6 +272,31 @@ static void normalizeDriverId(nsString& driverid) {
}
}
// 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
@ -337,157 +362,180 @@ GfxInfo::Init()
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);
}
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);
mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
mAdapterSubsysID = ParseIDFromDeviceID(mDeviceID, "&SUBSYS_", 8);
if (devinfo != INVALID_HANDLE_VALUE) {
HKEY key;
LONG result;
WCHAR value[255];
DWORD dwcbData;
SP_DEVINFO_DATA devinfoData;
DWORD memberIndex = 0;
// 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);
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 (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");
@ -758,6 +806,8 @@ 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:
@ -942,6 +992,13 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature,
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 &&

View File

@ -61,6 +61,7 @@ namespace widget {
class WinUtils {
public:
enum WinVersion {
WIN2K_VERSION = 0x500,
WINXP_VERSION = 0x501,
WIN2K3_VERSION = 0x502,
VISTA_VERSION = 0x600,

View File

@ -46,9 +46,10 @@
#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,
@ -57,7 +58,7 @@ static nsresult GetColorFromTheme(nsUXThemeClass cls,
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);
@ -74,10 +75,22 @@ static PRInt32 GetSystemParam(long flag, PRInt32 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
@ -186,8 +199,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
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;
@ -195,8 +208,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
}
// 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))
@ -271,8 +284,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
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))
@ -282,8 +294,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
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))
@ -393,7 +405,7 @@ nsLookAndFeel::GetIntImpl(IntID aID, PRInt32 &aResult)
aResult = 3;
break;
case eIntID_WindowsClassic:
aResult = !IsAppThemed();
aResult = !nsUXThemeData::IsAppThemed();
break;
case eIntID_TouchEnabled:
aResult = 0;
@ -421,6 +433,7 @@ nsLookAndFeel::GetIntImpl(IntID aID, PRInt32 &aResult)
break;
case eIntID_AlertNotificationOrigin:
aResult = 0;
if (gSHAppBarMessage)
{
// Get task bar window handle
HWND shellWindow = FindWindowW(L"Shell_TrayWnd", NULL);
@ -431,7 +444,7 @@ nsLookAndFeel::GetIntImpl(IntID aID, PRInt32 &aResult)
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.
@ -506,5 +519,11 @@ 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;
}

View File

@ -166,13 +166,13 @@ static bool IsTopLevelMenu(nsIFrame *aFrame)
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);
@ -192,8 +192,8 @@ 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)
@ -210,12 +210,12 @@ static SIZE GetCheckboxBGBounds(HANDLE theme, HDC hdc)
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);
@ -276,7 +276,7 @@ static HRESULT DrawThemeBGRTLAware(HANDLE theme, HDC hdc, int part, int state,
}
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)
@ -285,7 +285,7 @@ static HRESULT DrawThemeBGRTLAware(HANDLE theme, HDC hdc, int part, int state,
}
// 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);
}
/*
@ -383,7 +383,7 @@ 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];
@ -397,7 +397,7 @@ static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
// 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];
@ -412,7 +412,7 @@ static void OffsetBackgroundRect(RECT& rect, CaptionButton button) {
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
@ -431,9 +431,8 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
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:
@ -558,7 +557,7 @@ 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;
@ -635,7 +634,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
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
@ -702,11 +701,9 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
// 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;
@ -779,8 +776,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
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;
@ -868,7 +864,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
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 {
@ -1000,8 +996,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
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
@ -1021,7 +1016,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
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
@ -1217,6 +1212,9 @@ nsNativeThemeWin::DrawWidgetBackground(nsRenderingContext* aContext,
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()) {
@ -1355,10 +1353,10 @@ RENDER_AGAIN:
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;
@ -1373,7 +1371,7 @@ RENDER_AGAIN:
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)
{
@ -1402,7 +1400,7 @@ RENDER_AGAIN:
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;
@ -1410,14 +1408,14 @@ RENDER_AGAIN:
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;
@ -1425,7 +1423,7 @@ RENDER_AGAIN:
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));
@ -1453,7 +1451,7 @@ RENDER_AGAIN:
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 ||
@ -1466,7 +1464,7 @@ RENDER_AGAIN:
// 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
@ -1489,8 +1487,7 @@ RENDER_AGAIN:
// 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);
@ -1528,7 +1525,7 @@ RENDER_AGAIN:
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)
@ -1540,12 +1537,12 @@ RENDER_AGAIN:
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 ||
@ -1599,8 +1596,7 @@ RENDER_AGAIN:
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!");
}
@ -1612,7 +1608,7 @@ RENDER_AGAIN:
* indeterminate progress bars.
*/
PRInt32 overlaySize;
if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
if (nsUXThemeData::sIsVistaOrLater) {
if (vertical) {
overlaySize = indeterminate ? kProgressVerticalIndeterminateOverlaySize
: kProgressVerticalOverlaySize;
@ -1656,17 +1652,16 @@ RENDER_AGAIN:
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);
}
}
@ -1712,6 +1707,9 @@ nsNativeThemeWin::GetWidgetBorder(nsDeviceContext* aContext,
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))
@ -1729,7 +1727,7 @@ nsNativeThemeWin::GetWidgetBorder(nsDeviceContext* aContext,
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;
@ -1819,13 +1817,13 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
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)
@ -1918,7 +1916,7 @@ nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext,
* 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.
@ -1977,10 +1975,13 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* a
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:
@ -2041,7 +2042,7 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* a
*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;
@ -2154,7 +2155,7 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* a
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;
@ -2216,7 +2217,7 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
}
// 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;
@ -2225,7 +2226,7 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
// 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))
{
@ -2348,12 +2349,12 @@ nsNativeThemeWin::GetWidgetTransparency(nsIFrame* aFrame, PRUint8 aWidgetType)
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;
}

View File

@ -184,6 +184,14 @@
#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

View File

@ -67,13 +67,32 @@ 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;
@ -102,6 +121,26 @@ 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");
@ -123,28 +162,38 @@ 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;
}
@ -152,7 +201,7 @@ nsUXThemeData::GetThemeDLL() {
#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;
}
@ -358,14 +407,14 @@ nsUXThemeData::UpdateNativeThemeInfo()
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,

View File

@ -127,7 +127,9 @@ public:
#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];
@ -151,6 +153,64 @@ public:
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);

View File

@ -113,7 +113,6 @@
#include <process.h>
#include <commctrl.h>
#include <unknwn.h>
#include <psapi.h>
#include "prlog.h"
#include "prtime.h"
@ -1274,8 +1273,7 @@ NS_METHOD nsWindow::IsVisible(bool & bState)
// 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);
@ -1289,15 +1287,14 @@ void nsWindow::SetThemeRegion()
// so default constants are used for part and state. At some point we might need part and
// state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
// change shape based on state haven't come up.
if (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);
@ -6360,7 +6357,7 @@ nsWindow::InitMouseWheelScrollData()
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) {
@ -7461,12 +7458,22 @@ 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;
@ -7478,7 +7485,7 @@ static bool IsElantechHelperWindow(HWND aHWND)
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) {

View File

@ -758,9 +758,23 @@ PRUint8* nsWindowGfx::Data32BitTo1Bit(PRUint8* aImageData,
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.
@ -779,7 +793,7 @@ HBITMAP nsWindowGfx::DataToBitmap(PRUint8* aImageData,
{
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);

View File

@ -72,6 +72,7 @@ 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);
};

View File

@ -54,6 +54,7 @@ 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,

View File

@ -287,7 +287,9 @@ BlacklistNodeToTextValue(nsIDOMNode *aBlacklistNode, nsAString& aValue)
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;

View File

@ -70,6 +70,22 @@ static void SanitizeEnvironmentVariables()
}
}
// 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

View File

@ -205,12 +205,14 @@ StackWalkInitCriticalAddress()
#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;
@ -223,12 +225,116 @@ using namespace mozilla;
//
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;
@ -244,8 +350,82 @@ struct WalkStackData {
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;
@ -304,12 +484,79 @@ EnsureImageHlpInitialized()
::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.
@ -357,7 +604,7 @@ WalkStackMain64(struct WalkStackData* data)
// 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
@ -372,8 +619,8 @@ WalkStackMain64(struct WalkStackData* data)
&frame64,
&context,
NULL,
SymFunctionTableAccess64, // function table access routine
SymGetModuleBase64, // module base routine
_SymFunctionTableAccess64, // function table access routine
_SymGetModuleBase64, // module base routine
0
);
LeaveCriticalSection(&gDbgHelpCS);
@ -401,9 +648,106 @@ WalkStackMain64(struct WalkStackData* data)
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)
{
@ -441,7 +785,7 @@ WalkStackThread(void* aData)
PrintError("ThreadSuspend");
}
else {
WalkStackMain64(data);
PerformStackWalk(data);
ret = ::ResumeThread(data->thread);
if (ret == -1) {
@ -515,7 +859,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
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);
@ -556,12 +900,44 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
}
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;
@ -579,12 +955,15 @@ static BOOL CALLBACK callbackEspecial64(
? (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
}
/*
@ -596,6 +975,61 @@ static BOOL CALLBACK callbackEspecial64(
* 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
@ -612,6 +1046,7 @@ static BOOL CALLBACK callbackEspecial64(
#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;
@ -628,7 +1063,7 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, PIMAGEHLP_MODULE
* 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;
@ -642,14 +1077,14 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, PIMAGEHLP_MODULE
// 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");
}
@ -659,10 +1094,10 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, PIMAGEHLP_MODULE
* 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));
@ -671,6 +1106,7 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, PIMAGEHLP_MODULE
return retval;
}
#endif
bool
EnsureSymInitialized()
@ -686,13 +1122,13 @@ EnsureSymInitialized()
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;
}
@ -717,42 +1153,97 @@ NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
// 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);
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) {
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;
}
}
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 (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;
ok = SymFromAddr(myProcess, addr, &displacement, pSymbol);
DWORD64 displacement;
if (ok) {
PL_strncpyz(aDetails->function, pSymbol->Name,
sizeof(aDetails->function));
aDetails->foffset = displacement;
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;
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
@ -763,12 +1254,23 @@ 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);

View File

@ -673,7 +673,7 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
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)
{

View File

@ -110,6 +110,9 @@ unsigned char *_mbsstr( const unsigned char *str,
#define DRIVE_REMOTE 4
#endif
ILCreateFromPathWPtr nsLocalFile::sILCreateFromPathW = NULL;
SHOpenFolderAndSelectItemsPtr nsLocalFile::sSHOpenFolderAndSelectItems = NULL;
class nsDriveEnumerator : public nsISimpleEnumerator
{
public:
@ -2713,6 +2716,19 @@ nsLocalFile::SetPersistentDescriptor(const nsACString &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)
{
@ -2734,31 +2750,85 @@ nsLocalFile::SetFileAttributesWin(PRUint32 aAttribs)
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;
}
@ -2767,7 +2837,7 @@ nsLocalFile::Reveal()
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 {
@ -2780,13 +2850,13 @@ nsLocalFile::Reveal()
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;
@ -2796,7 +2866,7 @@ nsLocalFile::Reveal()
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);
@ -3105,6 +3175,21 @@ 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

View File

@ -56,6 +56,11 @@
#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
{
@ -123,6 +128,11 @@ private:
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

View File

@ -103,6 +103,7 @@ private:
// protected with mLock.
PRInt32 mExitValue;
#if defined(PROCESSMODEL_WINAPI)
typedef DWORD (WINAPI*GetProcessIdPtr)(HANDLE process);
HANDLE mProcess;
#elif !defined(XP_MACOSX)
PRProcess *mProcess;

View File

@ -500,7 +500,13 @@ nsProcess::RunProcess(bool blocking, char **my_argv, nsIObserver* observer,
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;