Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1364 lines
38 KiB

/********************************************************************/
/** Copyright(c) 1995 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: main.c
//
// Description: This module contains the main procedure of the Dynamic
// Interface Manager server service. It will contain code to
// initialize and install itself. It also contains
// code to respond to the server controller. It will also
// handle service shutdown.
//
// History: May 11,1995. NarenG Created original version.
//
#define _ALLOCATE_DIM_GLOBALS_
#include "dimsvcp.h"
#include <winsvc.h>
#include <winuser.h>
#include <dbt.h>
#include <ndisguid.h>
#include <wmium.h>
#include <rpc.h>
#include <iaspolcy.h>
#include <iasext.h>
#include <lmserver.h>
#include <srvann.h>
#include <ddmif.h>
#define RAS_CONTROL_CONFIGURE 128
//**
//
// Call: MediaSenseCallback
//
// Returns: None
//
// Description:
//
VOID
WINAPI
MediaSenseCallback(
PWNODE_HEADER pWnodeHeader,
UINT_PTR NotificationContext
)
{
ROUTER_INTERFACE_OBJECT * pIfObject;
PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
LPWSTR lpwsName = (LPWSTR)RtlOffsetToPointer(
pWnode,
pWnode->OffsetInstanceName );
if ( (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
||
(gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
{
return;
}
//
// Get the information for the media disconnect.
//
if ( memcmp( &(pWnodeHeader->Guid),
&GUID_NDIS_STATUS_MEDIA_DISCONNECT,
sizeof( GUID ) ) == 0 )
{
DIMTRACE1("MediaSenseCallback for sense disconnect called for %ws",
lpwsName );
IfObjectNotifyOfMediaSenseChange();
}
else
{
//
// Get the information for the media connect.
//
if ( memcmp( &(pWnodeHeader->Guid),
&GUID_NDIS_STATUS_MEDIA_CONNECT,
sizeof( GUID ) ) == 0 )
{
DIMTRACE1("MediaSenseCallback for sense connect called for %ws",
lpwsName );
IfObjectNotifyOfMediaSenseChange();
}
}
}
//**
//
// Call: MediaSenseRegister
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD
MediaSenseRegister(
IN BOOL fRegister
)
{
DWORD dwRetCode = NO_ERROR;
PVOID pvDeliveryInfo = MediaSenseCallback;
dwRetCode = WmiNotificationRegistration(
(LPGUID)(&GUID_NDIS_STATUS_MEDIA_CONNECT),
(BOOLEAN)fRegister,
pvDeliveryInfo,
(ULONG_PTR)NULL,
NOTIFICATION_CALLBACK_DIRECT );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
dwRetCode = WmiNotificationRegistration(
(LPGUID)(&GUID_NDIS_STATUS_MEDIA_DISCONNECT),
(BOOLEAN)fRegister,
pvDeliveryInfo,
(ULONG_PTR)NULL,
NOTIFICATION_CALLBACK_DIRECT );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
return( NO_ERROR );
}
//**
//
// Call: BindingsNotificationsCallback
//
// Returns: None
//
// Description:
//
VOID
WINAPI
BindingsNotificationsCallback(
PWNODE_HEADER pWnodeHeader,
UINT_PTR NotificationContext
)
{
LPWSTR lpwszGUIDStart;
LPWSTR lpwszGUIDEnd;
LPWSTR lpwszGUID;
WCHAR wchGUIDSaveLast;
ROUTER_INTERFACE_OBJECT * pIfObject;
PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
LPWSTR lpwsName = (LPWSTR)RtlOffsetToPointer(
pWnode,
pWnode->OffsetInstanceName );
LPWSTR lpwsTransportName = (LPWSTR)RtlOffsetToPointer(
pWnode,
pWnode->DataBlockOffset );
if ( (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
||
(gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
{
return;
}
//
// Extract GUID from the \device\GUID name
//
lpwszGUID = lpwsTransportName + wcslen( lpwsTransportName ) + 1;
lpwszGUIDStart = wcsrchr( lpwszGUID, L'{' );
lpwszGUIDEnd = wcsrchr( lpwszGUID, L'}' );
if ( (lpwszGUIDStart != NULL )
&& (lpwszGUIDEnd != NULL ))
{
wchGUIDSaveLast = *(lpwszGUIDEnd+1);
EnterCriticalSection( &(gblInterfaceTable.CriticalSection));
*(lpwszGUIDEnd+1) = (WCHAR)NULL;
pIfObject = IfObjectGetPointerByName( lpwszGUIDStart, FALSE );
*(lpwszGUIDEnd+1) = wchGUIDSaveLast;
//
// If we got a bind notification
//
if ( memcmp( &(pWnodeHeader->Guid), &GUID_NDIS_NOTIFY_BIND, sizeof( GUID ) ) == 0)
{
DIMTRACE2("BindingsNotificationsCallback BIND for %ws,Transport=%ws",
lpwsName, lpwsTransportName );
//
// If we have this interface loaded.
//
if ( pIfObject != NULL )
{
//
// If this interface is being bound to IP
//
if ( _wcsicmp( L"TCPIP", lpwsTransportName ) == 0 )
{
DWORD dwTransportIndex = GetTransportIndex( PID_IP );
//
// If IP routermanager is loaded and this interface is not
// already registered with it
//
if (( dwTransportIndex != -1 ) &&
( pIfObject->Transport[dwTransportIndex].hInterface
== INVALID_HANDLE_VALUE ))
{
AddInterfacesToRouterManager( lpwszGUIDStart, PID_IP );
}
}
//
// If this interface is being bound to IPX
//
if ( _wcsicmp( L"NWLNKIPX", lpwsTransportName ) == 0 )
{
DWORD dwTransportIndex = GetTransportIndex( PID_IPX );
//
// If IPX routermanager is loaded and this interface is not
// already registered with it
//
if (( dwTransportIndex != -1 ) &&
( pIfObject->Transport[dwTransportIndex].hInterface
== INVALID_HANDLE_VALUE ))
{
AddInterfacesToRouterManager( lpwszGUIDStart, PID_IPX );
}
}
}
}
else if (memcmp( &(pWnodeHeader->Guid),&GUID_NDIS_NOTIFY_UNBIND,sizeof(GUID))==0)
{
if ( pIfObject != NULL )
{
//
// Get the information for the media connect.
//
DIMTRACE2("BindingsNotificationsCallback UNDBIND for %ws,Transport=%ws",
lpwsName, lpwsTransportName );
if ( _wcsicmp( L"TCPIP", lpwsTransportName ) == 0 )
{
IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IP );
}
if ( _wcsicmp( L"NWLNKIPX", lpwsTransportName ) == 0 )
{
IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IPX );
}
}
}
LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
}
}
//**
//
// Call: BindingsNotificationsRegister
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD
BindingsNotificationsRegister(
IN BOOL fRegister
)
{
DWORD dwRetCode = NO_ERROR;
PVOID pvDeliveryInfo = BindingsNotificationsCallback;
dwRetCode = WmiNotificationRegistration(
(LPGUID)(&GUID_NDIS_NOTIFY_BIND),
(BOOLEAN)fRegister,
pvDeliveryInfo,
(ULONG_PTR)NULL,
NOTIFICATION_CALLBACK_DIRECT );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
dwRetCode = WmiNotificationRegistration(
(LPGUID)(&GUID_NDIS_NOTIFY_UNBIND),
(BOOLEAN)fRegister,
pvDeliveryInfo,
(ULONG_PTR)NULL,
NOTIFICATION_CALLBACK_DIRECT );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
return( NO_ERROR );
}
//**
//
// Call: DimAnnounceServiceStatus
//
// Returns: none
//
// Description: Will simly call SetServiceStatus to inform the service
// control manager of this service's current status.
//
VOID
DimAnnounceServiceStatus(
VOID
)
{
BOOL dwRetCode;
ASSERT (gblDIMConfigInfo.hServiceStatus);
//
// Increment the checkpoint in a pending state:
//
switch( gblDIMConfigInfo.ServiceStatus.dwCurrentState )
{
case SERVICE_START_PENDING:
case SERVICE_STOP_PENDING:
gblDIMConfigInfo.ServiceStatus.dwCheckPoint++;
break;
default:
break;
}
dwRetCode = SetServiceStatus( gblDIMConfigInfo.hServiceStatus,
&gblDIMConfigInfo.ServiceStatus );
if ( dwRetCode == FALSE )
{
//TracePrintfExA( gblDIMConfigInfo.dwTraceId,
// TRACE_DIM,
// "SetServiceStatus returned %d", GetLastError() );
}
}
//**
//
// Call: DimCleanUp
//
// Returns: none
//
// Description: Will free any allocated memory, deinitialize RPC, deinitialize
// the kernel-mode server and unload it if it was loaded.
// This could have been called due to an error on SERVICE_START
// or normal termination.
//
VOID
DimCleanUp(
IN DWORD dwError
)
{
DWORD dwIndex;
//
// Announce that we are stopping
//
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 1;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
DimAnnounceServiceStatus();
if ( gbldwDIMComponentsLoaded & DIM_RPC_LOADED )
{
DimTerminateRPC();
}
//
// Stop the timer and delete the timer Q if there is one.
//
if ( gblDIMConfigInfo.hTimerQ != NULL )
{
if(gblDIMConfigInfo.hTimer != NULL)
{
RtlDeleteTimer(gblDIMConfigInfo.hTimerQ,
gblDIMConfigInfo.hTimer,
NULL);
gblDIMConfigInfo.hTimer = NULL;
}
RtlDeleteTimerQueueEx( gblDIMConfigInfo.hTimerQ, INVALID_HANDLE_VALUE );
gblDIMConfigInfo.hTimerQ = NULL;
}
EnterCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
DeleteCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
{
//
// If we are not in LANOnly mode then stop DDM
//
if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
{
if ( gblhEventDDMServiceState != NULL )
{
SetEvent( gblhEventDDMServiceState );
}
}
//
// Wait for all threads in use to stop
//
while( gblDIMConfigInfo.dwNumThreadsRunning > 0 )
{
Sleep( 1000 );
}
}
// just to increment checkpoints
DimAnnounceServiceStatus();
//
// Tear down and free everything
//
if ( gbldwDIMComponentsLoaded & DIM_RMS_LOADED )
{
DimUnloadRouterManagers();
}
//
// Unregister for media sense
//
MediaSenseRegister( FALSE );
//
// Unregister for bind/unbind sense
//
BindingsNotificationsRegister( FALSE );
//
// Need to sleep to give the router managers a change to unload
// bug# 78711
//
Sleep( 2000 );
if ( gblhModuleDDM != NULL )
{
VOID (*DDMPostCleanup)( VOID ) = NULL;
DDMPostCleanup = (VOID(*)( VOID ))
GetDDMEntryPoint("DDMPostCleanup");
if(NULL != DDMPostCleanup)
{
//
// Call DDM to cleanup.
//
DDMPostCleanup();
}
FreeLibrary( gblhModuleDDM );
}
//
// If security object was created
//
if ( gbldwDIMComponentsLoaded & DIM_SECOBJ_LOADED )
{
DimSecObjDelete();
}
if ( gblDIMConfigInfo.hMprConfig != NULL )
{
MprConfigServerDisconnect( gblDIMConfigInfo.hMprConfig );
}
if ( gblhEventDDMTerminated != NULL )
{
CloseHandle( gblhEventDDMTerminated );
}
if ( gblhEventDDMServiceState != NULL )
{
CloseHandle( gblhEventDDMServiceState );
}
if ( gblhEventTerminateDIM != NULL )
{
CloseHandle( gblhEventTerminateDIM );
}
if ( gblhEventRMState != NULL )
{
CloseHandle( gblhEventRMState );
}
if ( gblDIMConfigInfo.hObjectRouterIdentity != NULL )
{
RouterIdentityObjectClose( gblDIMConfigInfo.hObjectRouterIdentity );
}
//
// Wait for everybody to release this and then delete it
//
EnterCriticalSection( &(gblInterfaceTable.CriticalSection) );
DeleteCriticalSection( &(gblInterfaceTable.CriticalSection) );
gbldwDIMComponentsLoaded = 0;
if ( gblDIMConfigInfo.dwTraceId != INVALID_TRACEID )
{
TraceDeregisterA( gblDIMConfigInfo.dwTraceId );
}
RouterLogDeregister( gblDIMConfigInfo.hLogEvents );
//
// Destroy private heap
//
if ( gblDIMConfigInfo.hHeap != NULL )
{
HeapDestroy( gblDIMConfigInfo.hHeap );
}
DIMTRACE1("DimCleanup completed for error %d", dwError );
//
// Zero init all the globals
//
gblRouterManagers = NULL;
gbldwDIMComponentsLoaded = 0;
gblhEventDDMTerminated = NULL;
gblhEventRMState = NULL;
gblhEventDDMServiceState = NULL;
gblhModuleDDM = NULL;
gblhEventTerminateDIM = NULL;
ZeroMemory( &gblInterfaceTable, sizeof( gblInterfaceTable ) );
{
SERVICE_STATUS_HANDLE svchandle = gblDIMConfigInfo.hServiceStatus;
ZeroMemory( &gblDIMConfigInfo, sizeof( gblDIMConfigInfo ) );
gblDIMConfigInfo.hServiceStatus = svchandle;
}
//
// Zero out only the procedure entrypoints. This is a side effect of
// the merge into svchost.exe since svchost doesn't unload mprdim
// anymore when router stops.
//
for ( dwIndex = 0;
gblDDMFunctionTable[dwIndex].lpEntryPointName != NULL;
dwIndex ++ )
{
gblDDMFunctionTable[dwIndex].pEntryPoint = NULL;
}
if ( dwError == NO_ERROR )
{
gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode = NO_ERROR;
}
else
{
gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode =
ERROR_SERVICE_SPECIFIC_ERROR;
}
gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOPPED;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
gblDIMConfigInfo.ServiceStatus.dwServiceSpecificExitCode = dwError;
gbldwDIMComponentsLoaded |= DIM_SERVICE_STOPPED;
DimAnnounceServiceStatus();
}
//**
//
// Call: ServiceHandlerEx
//
// Returns: none
//
// Description: Will respond to control requests from the service controller.
//
DWORD
ServiceHandlerEx(
IN DWORD dwControlCode,
IN DWORD dwEventType,
IN LPVOID lpEventData,
IN LPVOID lpContext
)
{
DWORD dwRetCode = NO_ERROR;
switch( dwControlCode )
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_STOP_PENDING)
||
( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_STOPPED ))
{
break;
}
DIMTRACE("Service control stop or shutdown called");
//
// Announce that we are stopping
//
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 1;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
DimAnnounceServiceStatus();
//
// Make sure service is started before initiating a stop
//
while( !( gbldwDIMComponentsLoaded & DIM_SERVICE_STARTED ) )
{
//
// Check to see if the we have already sent the
// stopped status. If it did, then bail.
//
if(gbldwDIMComponentsLoaded & DIM_SERVICE_STOPPED)
{
return dwRetCode;
}
Sleep( 1000 );
}
SetEvent( gblhEventTerminateDIM );
return( NO_ERROR );
case SERVICE_CONTROL_PAUSE:
if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_PAUSE_PENDING)
||
( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_PAUSED ))
break;
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_PAUSED;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_PAUSE_CONTINUE
| SERVICE_ACCEPT_SHUTDOWN;
SetEvent( gblhEventDDMServiceState );
break;
case SERVICE_CONTROL_CONTINUE:
if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_CONTINUE_PENDING )
||
( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_RUNNING ) )
break;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_PAUSE_CONTINUE
| SERVICE_ACCEPT_SHUTDOWN;
SetEvent( gblhEventDDMServiceState );
break;
case SERVICE_CONTROL_DEVICEEVENT:
if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_STOP_PENDING)
||
( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
SERVICE_STOPPED ))
{
break;
}
if ( lpEventData != NULL)
{
DEV_BROADCAST_DEVICEINTERFACE* pInfo =
(DEV_BROADCAST_DEVICEINTERFACE*)lpEventData;
if ( pInfo->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
{
ROUTER_INTERFACE_OBJECT * pIfObject = NULL;
if ( ( dwEventType == DBT_DEVICEARRIVAL ) ||
( dwEventType == DBT_DEVICEREMOVECOMPLETE ) )
{
//
// Extract GUID from the \device\GUID name
//
LPWSTR lpwszGUIDStart = wcsrchr( pInfo->dbcc_name, L'{' );
LPWSTR lpwszGUIDEnd = wcsrchr( pInfo->dbcc_name, L'}' );
if ( lpwszGUIDStart != NULL )
{
WCHAR wchGUIDSaveLast = *(lpwszGUIDEnd+1);
EnterCriticalSection( &(gblInterfaceTable.CriticalSection));
*(lpwszGUIDEnd+1) = (WCHAR)NULL;
pIfObject = IfObjectGetPointerByName( lpwszGUIDStart, FALSE );
*(lpwszGUIDEnd+1) = wchGUIDSaveLast;
if ( dwEventType == DBT_DEVICEARRIVAL )
{
if ( pIfObject == NULL )
{
DIMTRACE1("Device arrival:[%ws]", lpwszGUIDStart );
RegLoadInterfaces( lpwszGUIDStart, TRUE );
}
}
else
{
if ( pIfObject != NULL )
{
DIMTRACE1("Device removed:[%ws]", lpwszGUIDStart );
IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IP );
IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IPX);
IfObjectRemove( pIfObject->hDIMInterface );
}
}
LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
}
}
}
}
break;
case RAS_CONTROL_CONFIGURE:
//
// Code for dynamic configuration of RAP
//
DIMTRACE( "Received Remote Access Policy change control message" );
{
//
// thread needs to be COM initialized
//
HRESULT hResult = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if ( SUCCEEDED( hResult ) )
{
//
// configure, doesn't matter if the API call fails
//
ConfigureIas();
CoUninitialize();
}
}
break;
case SERVICE_CONTROL_POWEREVENT:
switch( dwEventType )
{
case PBT_APMQUERYSTANDBY:
case PBT_APMQUERYSUSPEND:
//
// Check if the this is running on a workstation
//
if (gblOsVersionInfo.wProductType == VER_NT_WORKSTATION)
{
//
// DIM has no say in the hibernation process on a
// workstation
//
break;
}
//
// If we are running as an RRAS server, on a Server platform,
// refuse the hibernate.
//
// This is not the best possible response, but given that
// connectivity is liable to break if an RRAS server is
// hibernated it is reasonable to prevent it (for now).
//
// In addition, the design of RTM currently (.net server)
// causes a delayed deletion of routes from the TCP/IP stack
// on a hibernate (routes deleted from IP Router Manager prior
// to hibernate are deleted from the stack when coming out of
// hibernate) leading to the loss of routes and hence
// connectivity. Until the design of RTM is fixed rejecting
// the hibernate query is the best solution.
//
if ( gblDIMConfigInfo.dwRouterRole &
( ROUTER_ROLE_LAN | ROUTER_ROLE_WAN | ROUTER_ROLE_RAS ) )
{
dwRetCode = ERROR_ACTIVE_CONNECTIONS;
}
break;
case PBT_APMRESUMECRITICAL:
default:
{
break;
}
}
break;
case SERVICE_CONTROL_NETBINDADD:
case SERVICE_CONTROL_NETBINDREMOVE:
case SERVICE_CONTROL_NETBINDENABLE:
case SERVICE_CONTROL_NETBINDDISABLE:
break;
default:
return( ERROR_CALL_NOT_IMPLEMENTED );
break;
}
DimAnnounceServiceStatus();
return( dwRetCode );
}
//**
//
// Call: ServiceMain
//
// Returns: None
//
// Description: This is the main procedure for the DIM Server Service. It
// will be called when the service is supposed to start itself.
// It will do all service wide initialization.
//
VOID
ServiceMain(
IN DWORD argc, // Command line arguments. Will be ignored.
IN LPWSTR * lpwsServiceArgs
)
{
DIM_INFO DimInfo;
DWORD dwRetCode;
DWORD dwIndex;
DWORD (*DDMServiceInitialize)( DIM_INFO * );
VOID (*DDMServicePostListens)( VOID *) = NULL;
UNREFERENCED_PARAMETER( argc );
UNREFERENCED_PARAMETER( lpwsServiceArgs );
gbldwDIMComponentsLoaded &= ~(DIM_SERVICE_STOPPED);
gblDIMConfigInfo.hServiceStatus = RegisterServiceCtrlHandlerEx(
TEXT("remoteaccess"),
ServiceHandlerEx,
NULL );
if ( !gblDIMConfigInfo.hServiceStatus )
{
return;
}
gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
DimAnnounceServiceStatus();
gblDIMConfigInfo.dwTraceId = TraceRegisterA( "Router" );
try {
//
// Mutex around the interface table
//
InitializeCriticalSection( &(gblInterfaceTable.CriticalSection) );
//
// Mutex around setting router identity attributes
//
InitializeCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
}
except (EXCEPTION_EXECUTE_HANDLER) {
return;
}
gblDIMConfigInfo.hLogEvents = RouterLogRegister( DIM_SERVICE_NAME );
/*
if ( gblDIMConfigInfo.hLogEvents == NULL )
{
DimCleanUp( GetLastError() );
return;
}
*/
//
// Create DIM private heap
//
gblDIMConfigInfo.hHeap = HeapCreate( 0, DIM_HEAP_INITIAL_SIZE,
DIM_HEAP_MAX_SIZE );
if ( gblDIMConfigInfo.hHeap == NULL )
{
DimCleanUp( GetLastError() );
return;
}
//
// Lead DIM parameters from the registry
//
if ( ( dwRetCode = RegLoadDimParameters() ) != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
DimAnnounceServiceStatus();
//
// Create event that will be used by DIM to make sure all the Router
// Managers have shut down when DIM is stopping.
//
gblhEventRMState = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( gblhEventRMState == (HANDLE)NULL )
{
DimCleanUp( GetLastError() );
return;
}
//
// Announce that we have successfully started.
//
gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_POWEREVENT
| SERVICE_ACCEPT_PAUSE_CONTINUE
| SERVICE_ACCEPT_SHUTDOWN;
DimAnnounceServiceStatus();
//
// Load the router managers
//
gbldwDIMComponentsLoaded |= DIM_RMS_LOADED;
if ( ( dwRetCode = RegLoadRouterManagers() ) != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
#if (WINVER >= 0x0501)
if ( gblDIMConfigInfo.dwNumRouterManagers == 0)
{
DimCleanUp( ROUTERLOG_IPX_TRANSPORT_NOT_SUPPORTED );
return;
}
#endif
//
// Create event that will be used to shutdown the DIM service
//
gblhEventTerminateDIM = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( gblhEventTerminateDIM == (HANDLE)NULL )
{
DimCleanUp( GetLastError() );
return;
}
//
// If not in LAN only mode load the Demand Dial Manager DLL
//
if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
{
//
// Create event that will be used by DDM to notify DIM that it has
// terminated
//
gblhEventDDMTerminated = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( gblhEventDDMTerminated == (HANDLE)NULL )
{
DimCleanUp( GetLastError() );
return;
}
//
// Create event that will be used by DIM to notify DDM that there is
// is a change is state of this service
//
gblhEventDDMServiceState = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( gblhEventDDMServiceState == (HANDLE)NULL )
{
DimCleanUp( GetLastError() );
return;
}
if ( ( dwRetCode = RegLoadDDM() ) != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
//
// Initialize the DDM
//
DDMServiceInitialize = (DWORD(*)( DIM_INFO * ))
GetDDMEntryPoint( "DDMServiceInitialize" );
if ( DDMServiceInitialize == NULL )
{
DimCleanUp( ERROR_PROC_NOT_FOUND );
return;
}
DDMServicePostListens = (VOID(*)( VOID *))
GetDDMEntryPoint( "DDMServicePostListens" );
if ( DDMServicePostListens == NULL )
{
DimCleanUp( ERROR_PROC_NOT_FOUND );
return;
}
DimInfo.pInterfaceTable = &gblInterfaceTable;
DimInfo.pRouterManagers = gblRouterManagers;
DimInfo.dwNumRouterManagers = gblDIMConfigInfo.dwNumRouterManagers;
DimInfo.pServiceStatus = &gblDIMConfigInfo.ServiceStatus;
DimInfo.phEventDDMServiceState = &gblhEventDDMServiceState;
DimInfo.phEventDDMTerminated = &gblhEventDDMTerminated;
DimInfo.dwTraceId = gblDIMConfigInfo.dwTraceId;
DimInfo.hLogEvents = gblDIMConfigInfo.hLogEvents;
DimInfo.lpdwNumThreadsRunning =
&(gblDIMConfigInfo.dwNumThreadsRunning);
DimInfo.lpfnIfObjectAllocateAndInit = IfObjectAllocateAndInit;
DimInfo.lpfnIfObjectGetPointerByName = IfObjectGetPointerByName;
DimInfo.lpfnIfObjectGetPointer = IfObjectGetPointer;
DimInfo.lpfnIfObjectRemove = IfObjectRemove;
DimInfo.lpfnIfObjectInsertInTable = IfObjectInsertInTable;
DimInfo.lpfnIfObjectWANDeviceInstalled = IfObjectWANDeviceInstalled;
DimInfo.lpfnRouterIdentityObjectUpdate
= RouterIdentityObjectUpdateDDMAttributes;
if ( ( dwRetCode = DDMServiceInitialize( &DimInfo ) ) != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
gbldwDIMComponentsLoaded |= DIM_DDM_LOADED;
//
// Initialize random number generator that is used by DDM
//
srand( GetTickCount() );
}
//
// What is the platform
//
RtlGetNtProductType( &(gblDIMConfigInfo.NtProductType) );
//
// Need this to do GUID to friendly name mapping
//
MprConfigServerConnect( NULL, &gblDIMConfigInfo.hMprConfig );
//
// Add the various interfaces
//
dwRetCode = RegLoadInterfaces( NULL, gblDIMConfigInfo.dwNumRouterManagers );
if ( dwRetCode != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
if ( ( dwRetCode = DimSecObjCreate() ) != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
gbldwDIMComponentsLoaded |= DIM_SECOBJ_LOADED;
dwRetCode = DimInitializeRPC(
gblDIMConfigInfo.dwRouterRole == ROUTER_ROLE_LAN );
if ( dwRetCode != NO_ERROR )
{
DimCleanUp( dwRetCode );
return;
}
gbldwDIMComponentsLoaded |= DIM_RPC_LOADED;
//
// Start a timer that when fired will go out and plumb the router attributes
//
if ( RtlCreateTimerQueue( &(gblDIMConfigInfo.hTimerQ) ) == STATUS_SUCCESS )
{
//
// We wait 5 minutes in the case where we are the router providing
// connectivity to the DC so we wait for all routing protocols to
// stabalize and propagate.
//
gblDIMConfigInfo.dwRouterIdentityDueTime = 5*60*1000;
RtlCreateTimer( gblDIMConfigInfo.hTimerQ,
&(gblDIMConfigInfo.hTimer),
RouterIdentityObjectUpdateAttributes,
(PVOID)TRUE,
gblDIMConfigInfo.dwRouterIdentityDueTime,
0,
WT_EXECUTEDEFAULT );
}
GetSystemTimeAsFileTime( (FILETIME*)&gblDIMConfigInfo.qwStartTime );
if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
{
if (DDMServicePostListens) //to keep prefast happy
DDMServicePostListens(NULL);
}
//
// Set the RAS bit for NetServerEnum
//
if( I_ScSetServiceBits( gblDIMConfigInfo.hServiceStatus,
SV_TYPE_DIALIN_SERVER,
TRUE,
TRUE,
NULL) == FALSE )
{
DimCleanUp( GetLastError() );
return;
}
//
// Register for device notifications. Specifically, we're interested
// in network adapters coming and going. If this fails, we proceed
// anyway.
//
{
DEV_BROADCAST_DEVICEINTERFACE PnpFilter;
ZeroMemory( &PnpFilter, sizeof( PnpFilter ) );
PnpFilter.dbcc_size = sizeof( PnpFilter );
PnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
PnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
gblDIMConfigInfo.hDeviceNotification =
RegisterDeviceNotification(
(HANDLE)gblDIMConfigInfo.hServiceStatus,
&PnpFilter,
DEVICE_NOTIFY_SERVICE_HANDLE );
if ( gblDIMConfigInfo.hDeviceNotification == NULL )
{
dwRetCode = GetLastError();
DIMTRACE1( "RegisterDeviceNotification failed with error %d",
dwRetCode );
DimCleanUp( dwRetCode );
return;
}
}
//
// Register for media sense events
//
if ( ( dwRetCode = MediaSenseRegister( TRUE ) ) != NO_ERROR )
{
DIMTRACE1( "Registering for media sense failed with dwRetCode = %d",
dwRetCode );
dwRetCode = NO_ERROR;
}
//
// Register for BIND/UNBIND notifications
//
if ( ( dwRetCode = BindingsNotificationsRegister( TRUE ) ) != NO_ERROR )
{
DIMTRACE1( "Registering for bindings notifications failed with dwRetCode = %d",
dwRetCode );
dwRetCode = NO_ERROR;
}
DIMTRACE( "Multi-Protocol Router started successfully" );
gbldwDIMComponentsLoaded |= DIM_SERVICE_STARTED;
//
// Notify all router managers that all interfaces have been loaded at
// service start.
//
for (dwIndex = 0; dwIndex < gblDIMConfigInfo.dwNumRouterManagers; dwIndex++)
{
gblRouterManagers[dwIndex].DdmRouterIf.RouterBootComplete();
}
//
// If we are a demand dial router
//
if ( gblDIMConfigInfo.dwRouterRole & ROUTER_ROLE_WAN )
{
DWORD dwXportIndex = GetTransportIndex( PID_IP );
//
// Initate persistent demand dial conenctions
//
DWORD (*IfObjectInitiatePersistentConnections)() =
(DWORD(*)())GetDDMEntryPoint("IfObjectInitiatePersistentConnections");
IfObjectInitiatePersistentConnections();
//
// If a WAN device is installed and IP is installed then we
// start advertizing on specific multicast address so as to make this
// router discoverable
//
IfObjectWANDeviceInstalled( DimInfo.fWANDeviceInstalled );
}
//
// Just wait here for DIM to terminate.
//
dwRetCode = WaitForSingleObject( gblhEventTerminateDIM, INFINITE );
if ( dwRetCode == WAIT_FAILED )
{
dwRetCode = GetLastError();
}
else
{
dwRetCode = NO_ERROR;
}
DimCleanUp( dwRetCode );
}