You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2134 lines
51 KiB
2134 lines
51 KiB
/*++
|
|
|
|
Copyright (c) 1998, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
svcmain.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code for the module's shared-access mode,
|
|
in which the module runs as a service rather than as a routing component.
|
|
|
|
Author:
|
|
|
|
Abolade Gbadegesin (aboladeg) 31-Aug-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <ras.h>
|
|
#include <rasuip.h>
|
|
#include <raserror.h>
|
|
#include <rasman.h>
|
|
#include "beacon.h"
|
|
|
|
HANDLE NhpAddressChangeEvent = NULL;
|
|
OVERLAPPED NhpAddressChangeOverlapped;
|
|
HANDLE NhpAddressChangeWaitHandle = NULL;
|
|
SERVICE_STATUS NhpServiceStatus;
|
|
SERVICE_STATUS_HANDLE NhpServiceStatusHandle = 0;
|
|
PIP_ADAPTER_BINDING_INFO NhpSharedPrivateLanBindingInfo = NULL;
|
|
GUID NhpSharedPrivateLanGuid;
|
|
ULONG NhpSharedPrivateLanIndex = (ULONG)-1;
|
|
HANDLE NhpStopDhcpEvent = NULL;
|
|
HANDLE NhpStopDnsEvent = NULL;
|
|
HANDLE NhpStopAlgEvent = NULL;
|
|
HANDLE NhpStopH323Event = NULL;
|
|
HANDLE NhpStopNatEvent = NULL;
|
|
BOOLEAN NhpRasmanReferenced = FALSE;
|
|
BOOLEAN NhpFwLoggingInitialized = FALSE;
|
|
BOOL NhPolicyAllowsFirewall = TRUE;
|
|
BOOL NhPolicyAllowsSharing = TRUE;
|
|
BOOLEAN NoLocalDns = TRUE; //whether DNS server is running or going to run on local host
|
|
BOOLEAN NhpNoLocalDhcp = TRUE; //whether DHCP server is running or goint to run on local host
|
|
BOOLEAN NhpQoSEnabled = FALSE;
|
|
IUdpBroadcastMapper *NhpUdpBroadcastMapper = NULL;
|
|
BOOLEAN NhpClassObjectsRegistered = FALSE;
|
|
|
|
|
|
//
|
|
// Pointer to the GlobalInterfaceTable for the process
|
|
//
|
|
|
|
IGlobalInterfaceTable *NhGITp = NULL;
|
|
|
|
//
|
|
// GIT cookie for the IHNetCfgMgr instance
|
|
//
|
|
|
|
DWORD NhCfgMgrCookie = 0;
|
|
|
|
const TCHAR c_szDnsServiceName[] = TEXT("DNS");
|
|
const TCHAR c_szDhcpServiceName[] = TEXT("DHCPServer");
|
|
|
|
ULONG
|
|
NhpEnableQoSWindowSizeAdjustment(
|
|
BOOLEAN fEnable
|
|
);
|
|
|
|
VOID
|
|
NhpStartAddressChangeNotification(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
NhpStopAddressChangeNotification(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
NhpUpdateConnectionsFolder(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
NhpUpdatePolicySettings(
|
|
VOID
|
|
);
|
|
|
|
|
|
HRESULT
|
|
NhGetHNetCfgMgr(
|
|
IHNetCfgMgr **ppCfgMgr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine obtains a pointer to the home networking configuration
|
|
manager.
|
|
|
|
Arguments:
|
|
|
|
ppCfgMgr - receives the IHNetCfgMgr pointer. The caller must release
|
|
this pointer.
|
|
|
|
Return Value:
|
|
|
|
standard HRESULT
|
|
|
|
Environment:
|
|
|
|
COM must be initialized on the calling thread
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (NULL == NhGITp)
|
|
{
|
|
EnterCriticalSection(&NhLock);
|
|
|
|
if (NULL == NhGITp)
|
|
{
|
|
IHNetCfgMgr *pCfgMgr;
|
|
|
|
//
|
|
// Create the global interface table
|
|
//
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_StdGlobalInterfaceTable,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_PPV_ARG(IGlobalInterfaceTable, &NhGITp)
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Create the homenet configuration manager
|
|
//
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_HNetCfgMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_PPV_ARG(IHNetCfgMgr, &pCfgMgr)
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhGetHNetCfgMgr: Unable to create HNetCfgMgr (0x%08x)",
|
|
hr
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhGetHNetCfgMgr: Unable to create GIT (0x%08x)",
|
|
hr
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Store the CfgMgr pointer in the GIT
|
|
//
|
|
|
|
hr = NhGITp->RegisterInterfaceInGlobal(
|
|
pCfgMgr,
|
|
IID_IHNetCfgMgr,
|
|
&NhCfgMgrCookie
|
|
);
|
|
|
|
pCfgMgr->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhGetHNetCfgMgr: Unable to register HNetCfgMgr (0x%08x)",
|
|
hr
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&NhLock);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = NhGITp->GetInterfaceFromGlobal(
|
|
NhCfgMgrCookie,
|
|
IID_PPV_ARG(IHNetCfgMgr, ppCfgMgr)
|
|
);
|
|
}
|
|
|
|
return hr;
|
|
} // NhGetHNetCfgMgr
|
|
|
|
|
|
ULONG
|
|
NhMapGuidToAdapter(
|
|
PWCHAR Guid
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to map a GUID to an adapter index.
|
|
It does so by querying 'GetInterfaceInfo' for the array of interfaces,
|
|
which contains the GUID and adapter index for each interface.
|
|
|
|
Arguments:
|
|
|
|
Guid - the GUID to be mapped to an adapter index.
|
|
|
|
Return Value:
|
|
|
|
ULONG - the required adapter index
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG AdapterIndex = (ULONG)-1;
|
|
ULONG i;
|
|
ULONG GuidLength;
|
|
PIP_INTERFACE_INFO Info;
|
|
PWCHAR Name;
|
|
ULONG NameLength;
|
|
ULONG Size;
|
|
PROFILE("NhMapGuidToAdapter");
|
|
Size = 0;
|
|
GuidLength = lstrlenW(Guid);
|
|
if (GetInterfaceInfo(NULL, &Size) == ERROR_INSUFFICIENT_BUFFER) {
|
|
Info = reinterpret_cast<PIP_INTERFACE_INFO>(
|
|
HeapAlloc(GetProcessHeap(), 0, Size)
|
|
);
|
|
if (Info) {
|
|
if (GetInterfaceInfo(Info, &Size) == NO_ERROR) {
|
|
for (i = 0; i < (ULONG)Info->NumAdapters; i++) {
|
|
NameLength = lstrlenW(Info->Adapter[i].Name);
|
|
if (NameLength < GuidLength) { continue; }
|
|
Name = Info->Adapter[i].Name + (NameLength - GuidLength);
|
|
if (lstrcmpiW(Guid, Name) == 0) {
|
|
AdapterIndex = Info->Adapter[i].Index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, Info);
|
|
}
|
|
}
|
|
return AdapterIndex;
|
|
} // NhMapGuidToAdapter
|
|
|
|
|
|
VOID NTAPI
|
|
NhpAddressChangeCallbackRoutine(
|
|
PVOID Context,
|
|
BOOLEAN TimedOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked when a change to a local address is signalled.
|
|
It is responsible for updating the bindings of the private and public
|
|
interfaces, and re-requesting change notification.
|
|
|
|
Arguments:
|
|
|
|
none used.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROFILE("NhpAddressChangeCallbackRoutine");
|
|
NtSetEvent(NatConnectionNotifyEvent, NULL);
|
|
NhpStartAddressChangeNotification();
|
|
|
|
} // NhpAddressChangeCallbackRoutine
|
|
|
|
|
|
VOID
|
|
NhpDeletePrivateInterface(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to remove the private interface
|
|
from each shared-access component.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROFILE("NhpDeletePrivateInterface");
|
|
|
|
if (NhpStopDnsEvent) { DnsRmDeleteInterface(0); }
|
|
if (NhpStopDhcpEvent) { DhcpRmDeleteInterface(0); }
|
|
if (NhpStopAlgEvent) { AlgRmDeleteInterface(0); }
|
|
if (NhpStopH323Event) { H323RmDeleteInterface(0); }
|
|
if (NhpStopNatEvent) { NatRmDeleteInterface(0); }
|
|
RtlZeroMemory(&NhpSharedPrivateLanGuid, sizeof(NhpSharedPrivateLanGuid));
|
|
} // NhpDeletePrivateInterface
|
|
|
|
|
|
ULONG
|
|
NhpEnableQoSWindowSizeAdjustment(
|
|
BOOLEAN fEnable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Instructs PSCHED to enable or disable window size adjustment.
|
|
|
|
Arguments:
|
|
|
|
fEnable -- TRUE if adjustments are to be enabled; FALSE, to be disabled
|
|
|
|
Return Value:
|
|
|
|
ULONG -- Win32 error
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ulError = ERROR_SUCCESS;
|
|
DWORD dwValue;
|
|
WMIHANDLE hDataBlock = NULL;
|
|
GUID qosGuid;
|
|
|
|
PROFILE("NhpEnableQoSWindowSizeAdjustment");
|
|
|
|
do
|
|
{
|
|
//
|
|
// WmiOpenBlock doesn't take a const guid, se we need to
|
|
// copy the defind value
|
|
//
|
|
|
|
CopyMemory(&qosGuid, &GUID_QOS_ENABLE_WINDOW_ADJUSTMENT, sizeof(GUID));
|
|
|
|
|
|
//
|
|
// Obtain a handle to the data block
|
|
//
|
|
|
|
ulError =
|
|
WmiOpenBlock(
|
|
&qosGuid,
|
|
GENERIC_WRITE,
|
|
&hDataBlock
|
|
);
|
|
|
|
if (ERROR_SUCCESS != ulError)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpEnableQoSWindowSizeAdjustment: WmiOpenBlock = %u",
|
|
ulError
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the value for the data block
|
|
//
|
|
|
|
dwValue = (fEnable ? 1 : 0);
|
|
|
|
ulError =
|
|
WmiSetSingleInstanceW(
|
|
hDataBlock,
|
|
L"PSCHED",
|
|
0,
|
|
sizeof(dwValue),
|
|
&dwValue
|
|
);
|
|
|
|
if (ERROR_SUCCESS != ulError)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpEnableQoSWindowSizeAdjustment: WmiSetSingleInstanceW = %u",
|
|
ulError
|
|
);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
if (NULL != hDataBlock)
|
|
{
|
|
WmiCloseBlock(hDataBlock);
|
|
}
|
|
|
|
return ulError;
|
|
} // NhpEnableQoSWindowSizeAdjustment
|
|
|
|
|
|
VOID
|
|
NhpStartAddressChangeNotification(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to request notifications of changes
|
|
to local IP addresses. The notifications are signalled on an event
|
|
which is created in this routine, and are acted on in a callback routine
|
|
which is registered in this routine.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error;
|
|
NTSTATUS status;
|
|
HANDLE TcpipHandle;
|
|
PROFILE("NhpStartAddressChangeNotification");
|
|
|
|
//
|
|
// Create an event on which to receive notifications
|
|
// and register a callback routine to be invoked if the event is signalled.
|
|
// Then request notification of address changes on the event.
|
|
//
|
|
|
|
do {
|
|
|
|
EnterCriticalSection(&NhLock);
|
|
|
|
if (!NhpAddressChangeEvent) {
|
|
status =
|
|
NtCreateEvent(
|
|
&NhpAddressChangeEvent,
|
|
EVENT_ALL_ACCESS,
|
|
NULL,
|
|
SynchronizationEvent,
|
|
FALSE
|
|
);
|
|
if (!NT_SUCCESS(status)) { break; }
|
|
|
|
status =
|
|
RtlRegisterWait(
|
|
&NhpAddressChangeWaitHandle,
|
|
NhpAddressChangeEvent,
|
|
NhpAddressChangeCallbackRoutine,
|
|
NULL,
|
|
INFINITE,
|
|
0
|
|
);
|
|
if (!NT_SUCCESS(status)) { break; }
|
|
}
|
|
|
|
ZeroMemory(&NhpAddressChangeOverlapped, sizeof(OVERLAPPED));
|
|
NhpAddressChangeOverlapped.hEvent = NhpAddressChangeEvent;
|
|
|
|
Error = NotifyAddrChange(&TcpipHandle, &NhpAddressChangeOverlapped);
|
|
if (Error != ERROR_IO_PENDING) { break; }
|
|
|
|
LeaveCriticalSection(&NhLock);
|
|
return;
|
|
|
|
} while(FALSE);
|
|
|
|
//
|
|
// A failure has occurred, so cleanup and quit.
|
|
// We proceed in this case without notification of address changes.
|
|
//
|
|
|
|
NhpStopAddressChangeNotification();
|
|
LeaveCriticalSection(&NhLock);
|
|
|
|
} // NhpStartAddressChangeNotification
|
|
|
|
|
|
VOID
|
|
NhpStopAddressChangeNotification(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to stop notification of local IP address changes,
|
|
and to clean up resources used for handling notifications.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
EnterCriticalSection(&NhLock);
|
|
if (NhpAddressChangeWaitHandle) {
|
|
RtlDeregisterWait(NhpAddressChangeWaitHandle);
|
|
NhpAddressChangeWaitHandle = NULL;
|
|
}
|
|
if (NhpAddressChangeEvent) {
|
|
NtClose(NhpAddressChangeEvent);
|
|
NhpAddressChangeEvent = NULL;
|
|
}
|
|
LeaveCriticalSection(&NhLock);
|
|
} // NhpStopAddressChangeNotification
|
|
|
|
|
|
VOID
|
|
NhpUpdateConnectionsFolder(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to refresh the connections folder UI.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Environment:
|
|
|
|
COM must be initialized on the calling thread.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr;
|
|
INetConnectionRefresh *pNetConnectionRefresh;
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_ConnectionManager,
|
|
NULL,
|
|
CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
|
|
IID_PPV_ARG(INetConnectionRefresh, &pNetConnectionRefresh)
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pNetConnectionRefresh->RefreshAll();
|
|
pNetConnectionRefresh->Release();
|
|
}
|
|
} // NhpUpdateConnectionsFolder
|
|
|
|
|
|
BOOL
|
|
NhpUpdatePolicySettings(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to update the group policy settings.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
BOOL -- returns TRUE if the policy settings have changed since
|
|
the previous call.
|
|
|
|
Environment:
|
|
|
|
COM must be initialized on the calling thread.
|
|
|
|
--*/
|
|
|
|
{
|
|
INetConnectionUiUtilities *pNetConnUiUtil;
|
|
HRESULT hr;
|
|
BOOL fOldPolicyAllowsFirewall;
|
|
BOOL fOldPolicyAllowsSharing;
|
|
BOOL fPolicyAllowsFirewall;
|
|
BOOL fPolicyAllowsSharing;
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_NetConnectionUiUtilities,
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_PPV_ARG(INetConnectionUiUtilities, &pNetConnUiUtil)
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fPolicyAllowsFirewall =
|
|
pNetConnUiUtil->UserHasPermission(NCPERM_PersonalFirewallConfig);
|
|
fPolicyAllowsSharing =
|
|
pNetConnUiUtil->UserHasPermission(NCPERM_ShowSharedAccessUi);
|
|
|
|
pNetConnUiUtil->Release();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// On failure assume that policy permits everything.
|
|
//
|
|
|
|
fPolicyAllowsFirewall = TRUE;
|
|
fPolicyAllowsSharing = TRUE;
|
|
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpUpdatePolicySettings: Unable to create INetConnectionUiUtilities (0x%08x)",
|
|
hr
|
|
);
|
|
}
|
|
|
|
//
|
|
// Update global variables w/ new settings
|
|
//
|
|
|
|
fOldPolicyAllowsFirewall =
|
|
InterlockedExchange(
|
|
reinterpret_cast<LPLONG>(&NhPolicyAllowsFirewall),
|
|
static_cast<LONG>(fPolicyAllowsFirewall)
|
|
);
|
|
|
|
fOldPolicyAllowsSharing =
|
|
InterlockedExchange(
|
|
reinterpret_cast<LPLONG>(&NhPolicyAllowsSharing),
|
|
static_cast<LONG>(fPolicyAllowsSharing)
|
|
);
|
|
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpUpdatePolicySettings: NhPolicyAllowsFirewall=%i, NhPolicyAllowsSharing=%i",
|
|
NhPolicyAllowsFirewall,
|
|
NhPolicyAllowsSharing
|
|
);
|
|
|
|
return (fOldPolicyAllowsFirewall != fPolicyAllowsFirewall
|
|
|| fOldPolicyAllowsSharing != fPolicyAllowsSharing);
|
|
|
|
} // NhpUpdatePolicySettings
|
|
|
|
|
|
BOOLEAN
|
|
NhQueryScopeInformation(
|
|
PULONG Address,
|
|
PULONG Mask
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to retrieve information about the current scope
|
|
for automatic addressing.
|
|
|
|
Arguments:
|
|
|
|
Address - receives the address of the scope
|
|
|
|
Mask - receives the network mask of the scope
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if successful, FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
EnterCriticalSection(&NhLock);
|
|
if (0 == NhDhcpScopeAddress) {
|
|
LeaveCriticalSection(&NhLock);
|
|
return FALSE;
|
|
}
|
|
|
|
*Address = NhDhcpScopeAddress;
|
|
*Mask = NhDhcpScopeMask;
|
|
LeaveCriticalSection(&NhLock);
|
|
return TRUE;
|
|
|
|
} // NhQueryScopeInformation
|
|
|
|
ULONG NhpQueryServiceStartType(SC_HANDLE hService, DWORD * pdwStartType)
|
|
{
|
|
ASSERT(hService);
|
|
ASSERT(pdwStartType);
|
|
|
|
ULONG Error = ERROR_SUCCESS;
|
|
DWORD cbBuf = sizeof (QUERY_SERVICE_CONFIG) +
|
|
5 * (32 * sizeof(WCHAR));
|
|
LPQUERY_SERVICE_CONFIG pConfig = NULL;
|
|
|
|
pConfig = (LPQUERY_SERVICE_CONFIG) NH_ALLOCATE(cbBuf);
|
|
if (!pConfig)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
do {
|
|
if (!QueryServiceConfig(hService, pConfig, cbBuf, &cbBuf))
|
|
{
|
|
Error = GetLastError();
|
|
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
|
|
{
|
|
NH_FREE(pConfig);
|
|
pConfig = (LPQUERY_SERVICE_CONFIG) NH_ALLOCATE(cbBuf);
|
|
if (NULL == pConfig)
|
|
{
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
|
|
if (!QueryServiceConfig(hService, pConfig, cbBuf, &cbBuf))
|
|
{
|
|
Error = GetLastError();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Error = ERROR_SUCCESS;
|
|
*pdwStartType = pConfig->dwStartType;
|
|
|
|
} while(FALSE);
|
|
|
|
if (pConfig)
|
|
NH_FREE(pConfig);
|
|
|
|
return Error;
|
|
}
|
|
|
|
BOOL NhpIsServiceRunningOrGoingToRun(SC_HANDLE hScm, LPCTSTR pSvcName)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
SC_HANDLE hService = NULL;
|
|
DWORD dwStartType = 0;
|
|
|
|
hService = OpenService(hScm, pSvcName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
|
|
|
|
if (hService)
|
|
{
|
|
SERVICE_STATUS Status;
|
|
ZeroMemory(&Status, sizeof(Status));
|
|
|
|
if (ERROR_SUCCESS == NhpQueryServiceStartType(hService, &dwStartType) &&
|
|
SERVICE_AUTO_START == dwStartType)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else if (QueryServiceStatus(hService, &Status) &&
|
|
(SERVICE_RUNNING == Status.dwCurrentState ||
|
|
SERVICE_START_PENDING == Status.dwCurrentState))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NhpEnableICSDNS(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enables "ICS DNS".
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Win32 error.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error = NO_ERROR;
|
|
|
|
do
|
|
{
|
|
Error = DnsRmEnableInterface(0);
|
|
if (Error)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpEnableICSDNS: DnsRmEnableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
Error = DnsEnableSuffixQuery();
|
|
if (Error)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpEnableICSDNS: DnsEnableSuffixQuery=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NhpDisableICSDNS(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine disables "ICS DNS".
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Win32 error.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error = NO_ERROR;
|
|
|
|
do
|
|
{
|
|
Error = DnsRmDisableInterface(0);
|
|
if (Error)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpDisableICSDNS: DnsRmDisableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
Error = DnsDisableSuffixQuery();
|
|
if (Error)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhpDisableICSDNS: DnsDisableSuffixQuery=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NhStartICSProtocols(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine starts the DNS and DHCP modules.
|
|
|
|
Arguments:
|
|
|
|
Argument* - count and array of arguments specified to the service
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error = NO_ERROR;
|
|
IP_AUTO_DHCP_GLOBAL_INFO DhcpInfo = {
|
|
IPNATHLP_LOGGING_ERROR,
|
|
0,
|
|
7 * 24 * 60,
|
|
DEFAULT_SCOPE_ADDRESS,
|
|
DEFAULT_SCOPE_MASK,
|
|
0
|
|
};
|
|
IP_DNS_PROXY_GLOBAL_INFO DnsInfo = {
|
|
IPNATHLP_LOGGING_ERROR,
|
|
IP_DNS_PROXY_FLAG_ENABLE_DNS,
|
|
3
|
|
};
|
|
|
|
|
|
//
|
|
// Get ICS settings to see if these should be started...
|
|
//
|
|
|
|
do {
|
|
|
|
SC_HANDLE hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
|
|
|
|
//dont start the DNS module if DNS server is running on local host
|
|
if (hScm)
|
|
{
|
|
NoLocalDns = !NhpIsServiceRunningOrGoingToRun(hScm, c_szDnsServiceName);
|
|
}
|
|
|
|
if (NoLocalDns)
|
|
{
|
|
if (!(NhpStopDnsEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
Error = GetLastError();
|
|
break;
|
|
} else {
|
|
|
|
Error =
|
|
DnsRmStartProtocol(
|
|
NhpStopDnsEvent,
|
|
NULL,
|
|
&DnsInfo,
|
|
IP_NAT_VERSION,
|
|
sizeof(IP_DNS_PROXY_GLOBAL_INFO),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhStartICSProtocols: NhpStartICSDNS=%d",
|
|
Error
|
|
);
|
|
CloseHandle(NhpStopDnsEvent); NhpStopDnsEvent = NULL; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//dont start the DHCP module if DNS server is running on local host
|
|
|
|
if (hScm)
|
|
{
|
|
NhpNoLocalDhcp = !NhpIsServiceRunningOrGoingToRun(hScm, c_szDhcpServiceName);
|
|
}
|
|
|
|
if (NhpNoLocalDhcp)
|
|
{
|
|
if (!(NhpStopDhcpEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
break;
|
|
} else {
|
|
NhQueryScopeInformation(
|
|
&DhcpInfo.ScopeNetwork, &DhcpInfo.ScopeMask
|
|
);
|
|
DhcpInfo.ScopeNetwork &= DhcpInfo.ScopeMask;
|
|
Error =
|
|
DhcpRmStartProtocol(
|
|
NhpStopDhcpEvent,
|
|
NULL,
|
|
&DhcpInfo,
|
|
IP_NAT_VERSION,
|
|
sizeof(DhcpInfo),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: DhcpRmStartProtocol=%d",
|
|
Error
|
|
);
|
|
CloseHandle(NhpStopDhcpEvent); NhpStopDhcpEvent = NULL; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (hScm)
|
|
CloseServiceHandle(hScm);
|
|
|
|
//
|
|
// Instruct QoS to enable window size adjustments. Any error that
|
|
// occurs here is not propagated, as ICS will still work correctly
|
|
// if this fails.
|
|
//
|
|
|
|
ULONG Error2 = NhpEnableQoSWindowSizeAdjustment(TRUE);
|
|
if (ERROR_SUCCESS == Error2)
|
|
{
|
|
NhpQoSEnabled = TRUE;
|
|
}
|
|
|
|
//
|
|
// Create the UDP broadcast mapper
|
|
//
|
|
|
|
HRESULT hr;
|
|
CComObject<CUdpBroadcastMapper> *pUdpBroadcast;
|
|
|
|
hr = CComObject<CUdpBroadcastMapper>::CreateInstance(&pUdpBroadcast);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pUdpBroadcast->AddRef();
|
|
|
|
hr = pUdpBroadcast->Initialize(&NatComponentReference);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pUdpBroadcast->QueryInterface(
|
|
IID_PPV_ARG(IUdpBroadcastMapper, &NhpUdpBroadcastMapper)
|
|
);
|
|
}
|
|
|
|
pUdpBroadcast->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
Error = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Start the Beaconing Service
|
|
//
|
|
|
|
StartBeaconSvr();
|
|
|
|
return NO_ERROR;
|
|
} while (FALSE);
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NhStopICSProtocols(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine stops the "ICS" modules (DNS, DHCP, QoSWindow, Beacon etc.)
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error = NO_ERROR;
|
|
|
|
//
|
|
// Stop the Beaconing Service
|
|
//
|
|
|
|
StopBeaconSvr();
|
|
|
|
//
|
|
// Cleanup the UDP broadcast mapper
|
|
//
|
|
|
|
if (NULL != NhpUdpBroadcastMapper)
|
|
{
|
|
NhpUdpBroadcastMapper->Shutdown();
|
|
NhpUdpBroadcastMapper->Release();
|
|
NhpUdpBroadcastMapper = NULL;
|
|
}
|
|
|
|
//
|
|
// Instruct QoS to disable window size adjustments
|
|
//
|
|
|
|
if (NhpQoSEnabled) {
|
|
NhpEnableQoSWindowSizeAdjustment(FALSE);
|
|
NhpQoSEnabled = FALSE;
|
|
}
|
|
|
|
//
|
|
// Remove the private interface from each shared-access component
|
|
//
|
|
|
|
NhpDeletePrivateInterface();
|
|
|
|
//
|
|
// Stop DHCP followed by DNS
|
|
//
|
|
|
|
if (NhpStopDhcpEvent) {
|
|
DhcpRmStopProtocol();
|
|
WaitForSingleObject(NhpStopDhcpEvent, INFINITE);
|
|
CloseHandle(NhpStopDhcpEvent); NhpStopDhcpEvent = NULL;
|
|
}
|
|
|
|
if (NhpStopDnsEvent) {
|
|
DnsRmStopProtocol();
|
|
WaitForSingleObject(NhpStopDnsEvent, INFINITE);
|
|
CloseHandle(NhpStopDnsEvent); NhpStopDnsEvent = NULL;
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NhUpdatePrivateInterface(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to add the private interface to each
|
|
shared-access component. It is also invoked when the private interface
|
|
is already added, but some change has occurred which requires that it
|
|
be updated (e.g. IP address change).
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Win32 error.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG AdapterIndex;
|
|
PIP_ADAPTER_BINDING_INFO BindingInfo;
|
|
ULONG Error;
|
|
ULONG Count;
|
|
GUID *pLanGuid;
|
|
HRESULT hr;
|
|
IHNetCfgMgr *pCfgMgr;
|
|
IHNetIcsSettings *pIcsSettings;
|
|
IEnumHNetIcsPrivateConnections *pEnum;
|
|
IHNetIcsPrivateConnection *pIcsConn;
|
|
IHNetConnection *pConn;
|
|
|
|
IP_NAT_INTERFACE_INFO NatInfo =
|
|
{
|
|
0,
|
|
0,
|
|
{ IP_NAT_VERSION, sizeof(RTR_INFO_BLOCK_HEADER), 0, { 0, 0, 0, 0 }}
|
|
};
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
|
|
|
|
PROFILE("NhUpdatePrivateInterface");
|
|
|
|
//
|
|
// We begin by reading the GUID from the configuration store,
|
|
// and we then map that GUID to an adapter index.
|
|
// Using that adapter index, we obtain the binding information
|
|
// for the private interface.
|
|
// We can then determine whether a change has occurred
|
|
// by comparing the previous and new GUID and binding information.
|
|
//
|
|
|
|
//
|
|
// Get the CfgMgr pointer out of the GIT
|
|
//
|
|
|
|
hr = NhGetHNetCfgMgr(&pCfgMgr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: GetInterfaceFromGlobal=0x%08x",
|
|
hr
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Get the ICS settings interface
|
|
//
|
|
|
|
hr = pCfgMgr->QueryInterface(IID_PPV_ARG(IHNetIcsSettings, &pIcsSettings));
|
|
pCfgMgr->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: QI for IHNetIcsSettings=0x%08x",
|
|
hr
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Get the enumeration of the ICS private interfaces
|
|
//
|
|
|
|
hr = pIcsSettings->EnumIcsPrivateConnections(&pEnum);
|
|
pIcsSettings->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: EnumIcsPrivateConnections=0x%08x",
|
|
hr
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Get the private connection
|
|
//
|
|
|
|
hr = pEnum->Next(1, &pIcsConn, &Count);
|
|
pEnum->Release();
|
|
|
|
if (FAILED(hr) || 1 != Count)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: pEnum->Next=0x%08x, Count=%d",
|
|
hr,
|
|
Count
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// QI for the IHNetConnection
|
|
//
|
|
|
|
hr = pIcsConn->QueryInterface(IID_PPV_ARG(IHNetConnection, &pConn));
|
|
pIcsConn->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: QI for IHNetConnection=0x%08x",
|
|
hr
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Get the GUID for the connection
|
|
//
|
|
|
|
hr = pConn->GetGuid(&pLanGuid);
|
|
pConn->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: GetGuid=0x%08x",
|
|
hr
|
|
);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Determine the adapter-index corresponding to the GUID
|
|
//
|
|
|
|
RtlStringFromGUID(*pLanGuid, &UnicodeString);
|
|
AdapterIndex = NhMapGuidToAdapter(UnicodeString.Buffer);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
if (AdapterIndex == (ULONG)-1) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: MapGuidToAdapter"
|
|
);
|
|
CoTaskMemFree(pLanGuid);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Retrieve the binding information for the adapter
|
|
//
|
|
|
|
BindingInfo = NhQueryBindingInformation(AdapterIndex);
|
|
if (!BindingInfo) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: QueryBindingInformation failed(2)\n"
|
|
);
|
|
CoTaskMemFree(pLanGuid);
|
|
return ERROR_NO_SUCH_INTERFACE;
|
|
}
|
|
|
|
//
|
|
// See if any change has occurred which requires an update.
|
|
//
|
|
|
|
if (RtlEqualMemory(pLanGuid, &NhpSharedPrivateLanGuid, sizeof(GUID)) &&
|
|
AdapterIndex == NhpSharedPrivateLanIndex &&
|
|
NhpSharedPrivateLanBindingInfo &&
|
|
BindingInfo->AddressCount ==
|
|
NhpSharedPrivateLanBindingInfo->AddressCount &&
|
|
BindingInfo->AddressCount &&
|
|
RtlEqualMemory(
|
|
&BindingInfo->Address[0],
|
|
&NhpSharedPrivateLanBindingInfo->Address[0],
|
|
sizeof(IP_LOCAL_BINDING)
|
|
)) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: no changes detected"
|
|
);
|
|
NH_FREE(BindingInfo);
|
|
CoTaskMemFree(pLanGuid);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// A change has occurred which requires an update.
|
|
// First we get rid of any existing private LAN interface,
|
|
// then we add the new interface to each component (NAT, DHCP, DNS proxy)
|
|
// and bind and enable the new interface.
|
|
//
|
|
|
|
NhpDeletePrivateInterface();
|
|
|
|
do {
|
|
|
|
Error =
|
|
NatRmAddInterface(
|
|
NULL,
|
|
0,
|
|
PERMANENT,
|
|
IF_TYPE_OTHER,
|
|
IF_ACCESS_BROADCAST,
|
|
IF_CONNECTION_DEDICATED,
|
|
&NatInfo,
|
|
IP_NAT_VERSION,
|
|
sizeof(NatInfo),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: NatRmAddInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (NhpNoLocalDhcp)
|
|
{
|
|
Error =
|
|
DhcpRmAddInterface(
|
|
NULL,
|
|
0,
|
|
PERMANENT,
|
|
IF_TYPE_OTHER,
|
|
IF_ACCESS_BROADCAST,
|
|
IF_CONNECTION_DEDICATED,
|
|
NULL,
|
|
IP_NAT_VERSION,
|
|
0,
|
|
0
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DhcpRmAddInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NoLocalDns)
|
|
{
|
|
Error =
|
|
DnsRmAddInterface(
|
|
NULL,
|
|
0,
|
|
PERMANENT,
|
|
IF_TYPE_OTHER,
|
|
IF_ACCESS_BROADCAST,
|
|
IF_CONNECTION_DEDICATED,
|
|
NULL,
|
|
IP_NAT_VERSION,
|
|
0,
|
|
0
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DnsRmAddInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
Error =
|
|
AlgRmAddInterface(
|
|
NULL,
|
|
0,
|
|
PERMANENT,
|
|
IF_TYPE_OTHER,
|
|
IF_ACCESS_BROADCAST,
|
|
IF_CONNECTION_DEDICATED,
|
|
NULL,
|
|
IP_NAT_VERSION,
|
|
0,
|
|
0
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: AlgRmAddInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
Error =
|
|
H323RmAddInterface(
|
|
NULL,
|
|
0,
|
|
PERMANENT,
|
|
IF_TYPE_OTHER,
|
|
IF_ACCESS_BROADCAST,
|
|
IF_CONNECTION_DEDICATED,
|
|
NULL,
|
|
IP_NAT_VERSION,
|
|
0,
|
|
0
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: H323RmAddInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Bind the private interface of each component
|
|
//
|
|
|
|
Error = NatBindInterface(0, NULL, BindingInfo, AdapterIndex);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: NatRmBindInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (NhpNoLocalDhcp)
|
|
{
|
|
Error = DhcpRmBindInterface(0, BindingInfo);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DhcpRmBindInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NoLocalDns)
|
|
{
|
|
Error = DnsRmBindInterface(0, BindingInfo);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DnsRmBindInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Error = AlgRmBindInterface(0, BindingInfo);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: AlgRmBindInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
Error = H323RmBindInterface(0, BindingInfo);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: H323RmBindInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enable the private interface for the components.
|
|
// The NAT private interface is always enabled, and therefore
|
|
// requires no additional call.
|
|
//
|
|
|
|
if (NhpNoLocalDhcp)
|
|
{
|
|
Error = DhcpRmEnableInterface(0);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DhcpRmEnableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NoLocalDns)
|
|
{
|
|
Error = DnsRmEnableInterface(0);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: DnsRmEnableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Error = AlgRmEnableInterface(0);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: AlgRmEnableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
Error = H323RmEnableInterface(0);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"NhUpdatePrivateInterface: H323RmEnableInterface=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The interface was activated successfully.
|
|
//
|
|
|
|
RtlCopyMemory(&NhpSharedPrivateLanGuid, pLanGuid, sizeof(GUID));
|
|
NhpSharedPrivateLanIndex = AdapterIndex;
|
|
CoTaskMemFree(pLanGuid);
|
|
if (NhpSharedPrivateLanBindingInfo) {
|
|
NH_FREE(NhpSharedPrivateLanBindingInfo);
|
|
}
|
|
NhpSharedPrivateLanBindingInfo = BindingInfo;
|
|
return NO_ERROR;
|
|
|
|
} while(FALSE);
|
|
|
|
NH_FREE(BindingInfo);
|
|
CoTaskMemFree(pLanGuid);
|
|
return Error;
|
|
|
|
} // NhUpdatePrivateInterface
|
|
|
|
|
|
VOID
|
|
ServiceHandler(
|
|
ULONG ControlCode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to control the 'SharedAccess' service.
|
|
|
|
Arguments:
|
|
|
|
ControlCode - indicates the requested operation
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN ComInitialized = FALSE;
|
|
HRESULT hr;
|
|
|
|
PROFILE("ServiceHandler");
|
|
if (ControlCode == IPNATHLP_CONTROL_UPDATE_CONNECTION) {
|
|
|
|
//
|
|
// Update our policy settings
|
|
//
|
|
|
|
NhpUpdatePolicySettings();
|
|
|
|
//
|
|
// Signal the configuration-changed event
|
|
//
|
|
|
|
NtSetEvent(NatConfigurationChangedEvent, NULL);
|
|
SignalBeaconSvr();
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_SETTINGS) {
|
|
|
|
//
|
|
// Update all state which depends on shared access settings
|
|
//
|
|
|
|
NatRemoveApplicationSettings();
|
|
NhUpdateApplicationSettings();
|
|
NatInstallApplicationSettings();
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_FWLOGGER) {
|
|
|
|
FwUpdateLoggingSettings();
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_AUTODIAL) {
|
|
|
|
NtSetEvent(NatConnectionNotifyEvent, NULL);
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_DNS_DISABLE) {
|
|
|
|
NhpDisableICSDNS();
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_DNS_ENABLE) {
|
|
|
|
NhpEnableICSDNS();
|
|
|
|
} else if (ControlCode == IPNATHLP_CONTROL_UPDATE_POLICY) {
|
|
|
|
if (NhpUpdatePolicySettings()) {
|
|
NtSetEvent(NatConfigurationChangedEvent, NULL);
|
|
}
|
|
|
|
} else if (ControlCode == SERVICE_CONTROL_STOP &&
|
|
NhpServiceStatus.dwCurrentState != SERVICE_STOPPED &&
|
|
NhpServiceStatus.dwCurrentState != SERVICE_STOP_PENDING) {
|
|
|
|
|
|
NhpServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
|
if (NhpServiceStatusHandle) {
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
}
|
|
|
|
if (NhpClassObjectsRegistered) {
|
|
_Module.RevokeClassObjects();
|
|
NhpClassObjectsRegistered = FALSE;
|
|
}
|
|
|
|
NhpStopAddressChangeNotification();
|
|
|
|
if (NhpStopNatEvent) {
|
|
NatRmStopProtocol();
|
|
WaitForSingleObject(NhpStopNatEvent, INFINITE);
|
|
CloseHandle(NhpStopNatEvent); NhpStopNatEvent = NULL;
|
|
}
|
|
|
|
if (NhpStopAlgEvent) {
|
|
AlgRmStopProtocol();
|
|
|
|
WaitForSingleObject(NhpStopAlgEvent, INFINITE);
|
|
CloseHandle(NhpStopAlgEvent); NhpStopAlgEvent = NULL;
|
|
}
|
|
|
|
if (NhpStopH323Event) {
|
|
H323RmStopProtocol();
|
|
WaitForSingleObject(NhpStopH323Event, INFINITE);
|
|
CloseHandle(NhpStopH323Event); NhpStopH323Event = NULL;
|
|
}
|
|
|
|
EnterCriticalSection(&NhLock);
|
|
NhFreeApplicationSettings();
|
|
if (NhpSharedPrivateLanBindingInfo) {
|
|
NH_FREE(NhpSharedPrivateLanBindingInfo);
|
|
NhpSharedPrivateLanBindingInfo = NULL;
|
|
}
|
|
LeaveCriticalSection(&NhLock);
|
|
NhpServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
|
NhResetComponentMode();
|
|
|
|
//
|
|
// Shutdown the firewall logging subsystem
|
|
//
|
|
|
|
if (NhpFwLoggingInitialized) {
|
|
FwCleanupLogger();
|
|
NhpFwLoggingInitialized = FALSE;
|
|
}
|
|
|
|
//
|
|
// Release our reference to RasMan
|
|
//
|
|
|
|
if (NhpRasmanReferenced) {
|
|
RasReferenceRasman(FALSE);
|
|
NhpRasmanReferenced = FALSE;
|
|
}
|
|
|
|
//
|
|
// Update the network connections folder (so that the firewall icons
|
|
// will disappear as necessary).
|
|
//
|
|
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
|
|
if (SUCCEEDED(hr)) {
|
|
ComInitialized = TRUE;
|
|
} else if (RPC_E_CHANGED_MODE == hr) {
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
NhpUpdateConnectionsFolder();
|
|
}
|
|
|
|
if (TRUE == ComInitialized) {
|
|
CoUninitialize();
|
|
}
|
|
|
|
NhStopEventLog();
|
|
}
|
|
if (NhpServiceStatusHandle) {
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
}
|
|
} // ServiceHandler
|
|
|
|
|
|
VOID
|
|
ServiceMain(
|
|
ULONG ArgumentCount,
|
|
PWCHAR ArgumentArray[]
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the entrypoint for the connection-sharing service.
|
|
It is responsible for initializing the module and starting operation.
|
|
|
|
Arguments:
|
|
|
|
Argument* - count and array of arguments specified to the service
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr;
|
|
ULONG Error;
|
|
BOOLEAN ComInitialized = FALSE;
|
|
|
|
IP_ALG_GLOBAL_INFO AlgInfo = {
|
|
IPNATHLP_LOGGING_ERROR,
|
|
0
|
|
};
|
|
|
|
IP_H323_GLOBAL_INFO H323Info = {
|
|
IPNATHLP_LOGGING_ERROR,
|
|
0
|
|
};
|
|
IP_NAT_GLOBAL_INFO NatInfo = {
|
|
IPNATHLP_LOGGING_ERROR,
|
|
0,
|
|
{ IP_NAT_VERSION, FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry), 0,
|
|
{ 0, 0, 0, 0 }}
|
|
};
|
|
|
|
PROFILE("ServiceMain");
|
|
|
|
do {
|
|
NhStartEventLog();
|
|
|
|
//
|
|
// Initialize service status, register a service control handler,
|
|
// and indicate that the service is starting
|
|
//
|
|
|
|
ZeroMemory(&NhpServiceStatus, sizeof(NhpServiceStatus));
|
|
NhpServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
|
|
NhpServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
NhpServiceStatusHandle =
|
|
RegisterServiceCtrlHandler(
|
|
TEXT("SharedAccess"), ServiceHandler
|
|
);
|
|
if (!NhpServiceStatusHandle) { break; }
|
|
|
|
//
|
|
// Attempt to set the component into 'Shared Access' mode.
|
|
// This module implements both shared-access and connection-sharing
|
|
// which are mutually exclusive, so we need to ensure that
|
|
// connection-sharing is not operational before proceeding.
|
|
//
|
|
|
|
if (!NhSetComponentMode(NhSharedAccessMode)) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: cannot enable Shared Access mode"
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure COM is initialized on this thread
|
|
//
|
|
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ComInitialized = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (RPC_E_CHANGED_MODE != hr)
|
|
{
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: Unable to initialize COM (0x%08x)",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(FALSE);
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: Unexpectedly in STA!"
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Obtain the current policy settings.
|
|
//
|
|
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
NhpUpdatePolicySettings();
|
|
|
|
//
|
|
// Reference RasMan. As we live in the same process as rasman, the
|
|
// normal SC dependency mechanism won't necessarily keep the rasman
|
|
// service alive (119042)
|
|
//
|
|
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
if (ERROR_SUCCESS != (Error = RasReferenceRasman(TRUE))) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: Unable to reference RasMan (0x%08x)",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
NhpRasmanReferenced = TRUE;
|
|
|
|
//
|
|
// Initialize the firewall logging subsystem
|
|
//
|
|
|
|
Error = FwInitializeLogger();
|
|
if (ERROR_SUCCESS != Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: FwInitializeLogger=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
NhpFwLoggingInitialized = TRUE;
|
|
|
|
//
|
|
// Register the class object for our notification sink
|
|
//
|
|
|
|
hr = _Module.RegisterClassObjects(
|
|
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE
|
|
);
|
|
|
|
if (FAILED(hr)) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: _Module.RegisterClassObjects=0x%08x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
NhpClassObjectsRegistered = TRUE;
|
|
|
|
//
|
|
// Start operations by loading the NAT, Ftp, ALG, and H.323 modules
|
|
//
|
|
|
|
NhpServiceStatus.dwWaitHint = 30000;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
if (!(NhpStopNatEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
break;
|
|
} else {
|
|
Error =
|
|
NatRmStartProtocol(
|
|
NhpStopNatEvent,
|
|
NULL,
|
|
&NatInfo,
|
|
IP_NAT_VERSION,
|
|
sizeof(NatInfo),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: NatRmStartProtocol=%d",
|
|
Error
|
|
);
|
|
CloseHandle(NhpStopNatEvent); NhpStopNatEvent = NULL; break;
|
|
}
|
|
}
|
|
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
if (!(NhpStopAlgEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
break;
|
|
} else {
|
|
Error =
|
|
AlgRmStartProtocol(
|
|
NhpStopAlgEvent,
|
|
NULL,
|
|
&AlgInfo,
|
|
IP_NAT_VERSION,
|
|
sizeof(AlgInfo),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: AlgRmStartProtocol=%d",
|
|
Error
|
|
);
|
|
CloseHandle(NhpStopAlgEvent); NhpStopAlgEvent = NULL; break;
|
|
}
|
|
}
|
|
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
if (!(NhpStopH323Event = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
break;
|
|
} else {
|
|
Error =
|
|
H323RmStartProtocol(
|
|
NhpStopH323Event,
|
|
NULL,
|
|
&H323Info,
|
|
IP_NAT_VERSION,
|
|
sizeof(H323Info),
|
|
1
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: H323RmStartProtocol=%d",
|
|
Error
|
|
);
|
|
CloseHandle(NhpStopH323Event); NhpStopH323Event = NULL; break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Start connection management. If needed, this will load the DNS and
|
|
// DHCP modules. The Beacon Service is also started.
|
|
//
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
Error = NatStartConnectionManagement();
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_INIT,
|
|
"ServiceMain: NatStartConnectionManagement=%d",
|
|
Error
|
|
);
|
|
break;
|
|
}
|
|
|
|
NhpServiceStatus.dwCheckPoint++;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
NhpStartAddressChangeNotification();
|
|
|
|
//
|
|
// Indicate that the service is now up and running.
|
|
//
|
|
|
|
NhpServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
NhpServiceStatus.dwWaitHint = 0;
|
|
NhpServiceStatus.dwCheckPoint = 0;
|
|
NhpServiceStatus.dwControlsAccepted =
|
|
SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PARAMCHANGE;
|
|
SetServiceStatus(NhpServiceStatusHandle, &NhpServiceStatus);
|
|
NhTrace(TRACE_FLAG_INIT, "ServiceMain: service started successfully");
|
|
|
|
//
|
|
// Ask the connections folder to update itself.
|
|
//
|
|
|
|
NhpUpdateConnectionsFolder();
|
|
|
|
//
|
|
// Uninitialize COM
|
|
//
|
|
|
|
if (TRUE == ComInitialized)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
return;
|
|
|
|
} while(FALSE);
|
|
|
|
//
|
|
// A failure occurred; do cleanup
|
|
//
|
|
|
|
NhpServiceStatus.dwWaitHint = 0;
|
|
NhpServiceStatus.dwCheckPoint = 0;
|
|
NhTrace(TRACE_FLAG_INIT, "ServiceMain: service could not start");
|
|
StopBeaconSvr();
|
|
|
|
//
|
|
// Uninitialize COM
|
|
//
|
|
|
|
if (TRUE == ComInitialized)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
ServiceHandler(SERVICE_CONTROL_STOP);
|
|
|
|
} // ServiceMain
|
|
|