зеркало из https://github.com/mozilla/pjs.git
Bug 465158 - Minefield Nightly fails to initiate dial-up login when using internet connection sharing, r=cbiesinger
This commit is contained in:
Родитель
417896cb6b
Коммит
4596cdf3f9
|
@ -167,6 +167,7 @@ nsIOService::nsIOService()
|
|||
, mOfflineForProfileChange(PR_FALSE)
|
||||
, mSettingOffline(PR_FALSE)
|
||||
, mSetOfflineValue(PR_FALSE)
|
||||
, mShutdown(PR_FALSE)
|
||||
, mManageOfflineStatus(PR_TRUE)
|
||||
, mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
|
||||
, mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
|
||||
|
@ -617,6 +618,11 @@ nsIOService::GetOffline(PRBool *offline)
|
|||
NS_IMETHODIMP
|
||||
nsIOService::SetOffline(PRBool offline)
|
||||
{
|
||||
// When someone wants to go online (!offline) after we got XPCOM shutdown
|
||||
// throw ERROR_NOT_AVAILABLE to prevent return to online state.
|
||||
if (mShutdown && !offline)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// SetOffline() may re-enter while it's shutting down services.
|
||||
// If that happens, save the most recent value and it will be
|
||||
// processed when the first SetOffline() call is done bringing
|
||||
|
@ -834,6 +840,11 @@ nsIOService::Observe(nsISupports *subject,
|
|||
}
|
||||
}
|
||||
else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
// Remember we passed XPCOM shutdown notification to prevent any
|
||||
// changes of the offline status from now. We must not allow going
|
||||
// online after this point.
|
||||
mShutdown = PR_TRUE;
|
||||
|
||||
SetOffline(PR_TRUE);
|
||||
|
||||
// Break circular reference.
|
||||
|
@ -951,6 +962,9 @@ nsIOService::TrackNetworkLinkStatusForOffline()
|
|||
if (!mNetworkLinkService)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mShutdown)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// check to make sure this won't collide with Autodial
|
||||
if (mSocketTransportService) {
|
||||
PRBool autodialEnabled = PR_FALSE;
|
||||
|
|
|
@ -140,6 +140,8 @@ private:
|
|||
PRPackedBool mSettingOffline;
|
||||
PRPackedBool mSetOfflineValue;
|
||||
|
||||
PRPackedBool mShutdown;
|
||||
|
||||
nsCOMPtr<nsPISocketTransportService> mSocketTransportService;
|
||||
nsCOMPtr<nsPIDNSService> mDNSService;
|
||||
nsCOMPtr<nsIProtocolProxyService2> mProxyService;
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
#include <winbase.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <winsock2.h>
|
||||
#include <NetCon.h>
|
||||
#include <objbase.h>
|
||||
#include <iprtrmib.h>
|
||||
#include <time.h>
|
||||
#include "prmem.h"
|
||||
#include "plstr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -51,6 +51,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNotifyAddrListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include <iptypes.h>
|
||||
#include <iphlpapi.h>
|
||||
|
@ -62,23 +63,21 @@ 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 sIPHelper;
|
||||
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)
|
||||
return;
|
||||
|
||||
if (!sIPHelper) {
|
||||
sIPHelper = LoadLibraryW(L"iphlpapi.dll");
|
||||
if (!sIPHelper)
|
||||
return;
|
||||
|
||||
if (sIPHelper) {
|
||||
sGetAdaptersAddresses = (GetAdaptersAddressesFunc)
|
||||
GetProcAddress(sIPHelper, "GetAdaptersAddresses");
|
||||
sGetAdaptersInfo = (GetAdaptersInfoFunc)
|
||||
|
@ -89,13 +88,25 @@ static void InitIPHelperLibrary(void)
|
|||
GetProcAddress(sIPHelper, "GetIpAddrTable");
|
||||
sNotifyAddrChange = (NotifyAddrChangeFunc)
|
||||
GetProcAddress(sIPHelper, "NotifyAddrChange");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FreeIPHelperLibrary(void)
|
||||
static void InitNetshellLibrary(void)
|
||||
{
|
||||
if (!sIPHelper)
|
||||
return;
|
||||
if (!sNetshell) {
|
||||
sNetshell = LoadLibraryW(L"Netshell.dll");
|
||||
if (sNetshell) {
|
||||
sNcFreeNetconProperties = (NcFreeNetconPropertiesFunc)
|
||||
GetProcAddress(sNetshell, "NcFreeNetconProperties");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FreeDynamicLibraries(void)
|
||||
{
|
||||
if (sIPHelper)
|
||||
{
|
||||
sGetAdaptersAddresses = nsnull;
|
||||
sGetAdaptersInfo = nsnull;
|
||||
sGetIfEntry = nsnull;
|
||||
|
@ -104,6 +115,13 @@ static void FreeIPHelperLibrary(void)
|
|||
|
||||
FreeLibrary(sIPHelper);
|
||||
sIPHelper = nsnull;
|
||||
}
|
||||
|
||||
if (sNetshell) {
|
||||
sNcFreeNetconProperties = nsnull;
|
||||
FreeLibrary(sNetshell);
|
||||
sNetshell = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsNotifyAddrListener,
|
||||
|
@ -114,22 +132,27 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsNotifyAddrListener,
|
|||
nsNotifyAddrListener::nsNotifyAddrListener()
|
||||
: mLinkUp(PR_TRUE) // assume true by default
|
||||
, mStatusKnown(PR_FALSE)
|
||||
, mCheckAttempted(PR_FALSE)
|
||||
, mShutdownEvent(nsnull)
|
||||
{
|
||||
mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
|
||||
GetVersionEx(&mOSVerInfo);
|
||||
InitIPHelperLibrary();
|
||||
}
|
||||
|
||||
nsNotifyAddrListener::~nsNotifyAddrListener()
|
||||
{
|
||||
NS_ASSERTION(!mThread, "nsNotifyAddrListener thread shutdown failed");
|
||||
FreeIPHelperLibrary();
|
||||
FreeDynamicLibraries();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNotifyAddrListener::GetIsLinkUp(PRBool *aIsUp)
|
||||
{
|
||||
if (!mCheckAttempted && !mStatusKnown) {
|
||||
mCheckAttempted = PR_TRUE;
|
||||
CheckLinkStatus();
|
||||
}
|
||||
|
||||
*aIsUp = mLinkUp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -151,6 +174,8 @@ nsNotifyAddrListener::Run()
|
|||
OVERLAPPED overlapped = { 0 };
|
||||
PRBool shuttingDown = PR_FALSE;
|
||||
|
||||
InitIPHelperLibrary();
|
||||
|
||||
overlapped.hEvent = ev;
|
||||
while (!shuttingDown) {
|
||||
HANDLE h;
|
||||
|
@ -318,7 +343,9 @@ nsNotifyAddrListener::CheckIPAddrTable(void)
|
|||
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)
|
||||
table->table[i].dwAddr != 0 &&
|
||||
// Nor a loopback
|
||||
table->table[i].dwAddr != 0x0100007F)
|
||||
linkUp = PR_TRUE;
|
||||
}
|
||||
mLinkUp = linkUp;
|
||||
|
@ -350,7 +377,11 @@ nsNotifyAddrListener::CheckAdaptersInfo(void)
|
|||
DWORD ret = sGetAdaptersInfo(0, &adaptersLen);
|
||||
if (ret == ERROR_BUFFER_OVERFLOW && adaptersLen > 0) {
|
||||
PIP_ADAPTER_INFO adapters = (PIP_ADAPTER_INFO) malloc(adaptersLen);
|
||||
if (sGetAdaptersInfo(adapters, &adaptersLen) == ERROR_SUCCESS) {
|
||||
if (!adapters)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
ret = sGetAdaptersInfo(adapters, &adaptersLen);
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
PRBool linkUp = PR_FALSE;
|
||||
PIP_ADAPTER_INFO ptr;
|
||||
|
||||
|
@ -368,12 +399,14 @@ nsNotifyAddrListener::CheckAdaptersInfo(void)
|
|||
else {
|
||||
PIP_ADDR_STRING ipAddr;
|
||||
for (ipAddr = &ptr->IpAddressList; ipAddr && !linkUp;
|
||||
ipAddr = ipAddr->Next)
|
||||
if (PL_strcmp(ipAddr->IpAddress.String, "0.0.0.0"))
|
||||
ipAddr = ipAddr->Next) {
|
||||
if (PL_strcmp(ipAddr->IpAddress.String, "0.0.0.0")) {
|
||||
linkUp = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mLinkUp = linkUp;
|
||||
mStatusKnown = PR_TRUE;
|
||||
free(adapters);
|
||||
|
@ -382,6 +415,113 @@ nsNotifyAddrListener::CheckAdaptersInfo(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
nsNotifyAddrListener::CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter)
|
||||
{
|
||||
if (!aAdapter->FirstUnicastAddress)
|
||||
return FALSE;
|
||||
|
||||
LPSOCKADDR aAddress = aAdapter->FirstUnicastAddress->Address.lpSockaddr;
|
||||
if (!aAddress)
|
||||
return FALSE;
|
||||
|
||||
PSOCKADDR_IN in_addr = (PSOCKADDR_IN)aAddress;
|
||||
PRBool isGateway = (aAddress->sa_family == AF_INET &&
|
||||
in_addr->sin_addr.S_un.S_un_b.s_b1 == 192 &&
|
||||
in_addr->sin_addr.S_un.S_un_b.s_b2 == 168 &&
|
||||
in_addr->sin_addr.S_un.S_un_b.s_b3 == 0 &&
|
||||
in_addr->sin_addr.S_un.S_un_b.s_b4 == 1);
|
||||
|
||||
if (isGateway)
|
||||
isGateway = CheckICSStatus(aAdapter->FriendlyName);
|
||||
|
||||
return isGateway;
|
||||
}
|
||||
|
||||
BOOL
|
||||
nsNotifyAddrListener::CheckICSStatus(PWCHAR aAdapterName)
|
||||
{
|
||||
InitNetshellLibrary();
|
||||
|
||||
// This method enumerates all privately shared connections and checks if some
|
||||
// of them has the same name as the one provided in aAdapterName. If such
|
||||
// connection is found in the collection the adapter is used as ICS gateway
|
||||
BOOL isICSGatewayAdapter = FALSE;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
nsRefPtr<INetSharingManager> netSharingManager;
|
||||
hr = CoCreateInstance(
|
||||
CLSID_NetSharingManager,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_INetSharingManager,
|
||||
getter_AddRefs(netSharingManager));
|
||||
|
||||
nsRefPtr<INetSharingPrivateConnectionCollection> privateCollection;
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = netSharingManager->get_EnumPrivateConnections(
|
||||
ICSSC_DEFAULT,
|
||||
getter_AddRefs(privateCollection));
|
||||
}
|
||||
|
||||
nsRefPtr<IEnumNetSharingPrivateConnection> privateEnum;
|
||||
if (SUCCEEDED(hr)) {
|
||||
nsRefPtr<IUnknown> privateEnumUnknown;
|
||||
hr = privateCollection->get__NewEnum(getter_AddRefs(privateEnumUnknown));
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = privateEnumUnknown->QueryInterface(
|
||||
IID_IEnumNetSharingPrivateConnection,
|
||||
getter_AddRefs(privateEnum));
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
ULONG fetched;
|
||||
VARIANT connectionVariant;
|
||||
while (!isICSGatewayAdapter &&
|
||||
SUCCEEDED(hr = privateEnum->Next(1, &connectionVariant,
|
||||
&fetched)) &&
|
||||
fetched) {
|
||||
if (connectionVariant.vt != VT_UNKNOWN) {
|
||||
// We should call VariantClear here but it needs to link
|
||||
// with oleaut32.lib that produces a Ts incrase about 10ms
|
||||
// that is undesired. As it is quit unlikely the result would
|
||||
// be of a different type anyway, let's pass the variant
|
||||
// unfreed here.
|
||||
NS_ERROR("Variant of unexpected type, expecting VT_UNKNOWN, we probably leak it!");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsRefPtr<INetConnection> connection;
|
||||
hr = connectionVariant.punkVal->QueryInterface(
|
||||
IID_INetConnection,
|
||||
getter_AddRefs(connection));
|
||||
connectionVariant.punkVal->Release();
|
||||
|
||||
NETCON_PROPERTIES *properties;
|
||||
if (SUCCEEDED(hr))
|
||||
hr = connection->GetProperties(&properties);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (!wcscmp(properties->pszwName, aAdapterName))
|
||||
isICSGatewayAdapter = TRUE;
|
||||
|
||||
if (sNcFreeNetconProperties)
|
||||
sNcFreeNetconProperties(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return isICSGatewayAdapter;
|
||||
}
|
||||
|
||||
DWORD
|
||||
nsNotifyAddrListener::CheckAdaptersAddresses(void)
|
||||
{
|
||||
|
@ -392,28 +532,36 @@ nsNotifyAddrListener::CheckAdaptersAddresses(void)
|
|||
if (!sGetAdaptersAddresses)
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
|
||||
ULONG len = 0;
|
||||
ULONG len = 16384;
|
||||
|
||||
DWORD ret = sGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
|
||||
if (ret == ERROR_BUFFER_OVERFLOW) {
|
||||
PIP_ADAPTER_ADDRESSES addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
|
||||
if (addresses) {
|
||||
if (!addresses)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
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 = sGetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &len);
|
||||
}
|
||||
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_ADDRESSES ptr;
|
||||
BOOL linkUp = FALSE;
|
||||
|
||||
for (ptr = addresses; !linkUp && ptr; ptr = ptr->Next) {
|
||||
if (ptr->OperStatus == IfOperStatusUp &&
|
||||
ptr->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
|
||||
ptr->IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
|
||||
!CheckIsGateway(ptr))
|
||||
linkUp = TRUE;
|
||||
}
|
||||
mLinkUp = linkUp;
|
||||
mStatusKnown = TRUE;
|
||||
}
|
||||
free(addresses);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#define NSNOTIFYADDRLISTENER_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <iptypes.h>
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIObserver.h"
|
||||
|
@ -74,6 +76,7 @@ protected:
|
|||
|
||||
PRPackedBool mLinkUp;
|
||||
PRPackedBool mStatusKnown;
|
||||
PRPackedBool mCheckAttempted;
|
||||
|
||||
nsresult Shutdown(void);
|
||||
nsresult SendEventToUI(const char *aEventID);
|
||||
|
@ -82,6 +85,8 @@ protected:
|
|||
DWORD CheckIPAddrTable(void);
|
||||
DWORD CheckAdaptersInfo(void);
|
||||
DWORD CheckAdaptersAddresses(void);
|
||||
BOOL CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter);
|
||||
BOOL CheckICSStatus(PWCHAR aAdapterName);
|
||||
void CheckLinkStatus(void);
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
|
Загрузка…
Ссылка в новой задаче