/*++ Copyright (c) 1998, Microsoft Corporation Module Name: rmdns.c Abstract: This module contains routines for the DNS allocator module's interface to the IP router-manager. (See ROUTPROT.H for details). Author: Abolade Gbadegesin (aboladeg) 4-Mar-1998 Revision History: --*/ #include "precomp.h" #pragma hdrstop #define DNS_SERVICE_NAME TEXT("DNS") COMPONENT_REFERENCE DnsComponentReference; PIP_DNS_PROXY_GLOBAL_INFO DnsGlobalInfo = NULL; CRITICAL_SECTION DnsGlobalInfoLock; SOCKET DnsGlobalSocket = INVALID_SOCKET; HANDLE DnsNotificationEvent; ULONG DnsProtocolStopped = 0; const MPR_ROUTING_CHARACTERISTICS DnsRoutingCharacteristics = { MS_ROUTER_VERSION, MS_IP_DNS_PROXY, RF_ROUTING|RF_ADD_ALL_INTERFACES, DnsRmStartProtocol, DnsRmStartComplete, DnsRmStopProtocol, DnsRmGetGlobalInfo, DnsRmSetGlobalInfo, NULL, NULL, DnsRmAddInterface, DnsRmDeleteInterface, DnsRmInterfaceStatus, DnsRmGetInterfaceInfo, DnsRmSetInterfaceInfo, DnsRmGetEventMessage, NULL, NULL, NULL, NULL, NULL, DnsRmMibCreate, DnsRmMibDelete, DnsRmMibGet, DnsRmMibSet, DnsRmMibGetFirst, DnsRmMibGetNext, NULL, NULL }; IP_DNS_PROXY_STATISTICS DnsStatistics; SUPPORT_FUNCTIONS DnsSupportFunctions; VOID DnsCleanupModule( VOID ) /*++ Routine Description: This routine is invoked to cleanup the DNS module. Arguments: none. Return Value: none. Environment: Invoked from within a 'DllMain' routine on 'DLL_PROCESS_DETACH'. --*/ { DnsShutdownInterfaceManagement(); DnsShutdownTableManagement(); DnsShutdownFileManagement(); DeleteCriticalSection(&DnsGlobalInfoLock); DeleteComponentReference(&DnsComponentReference); } // DnsCleanupModule VOID DnsCleanupProtocol( VOID ) /*++ Routine Description: This routine is invoked to cleanup the DNS protocol-component after a 'StopProtocol'. It runs when the last reference to the DHCP component is released. (See 'COMPREF.H'). Arguments: none. Return Value: none. Environment: Invoked from within an arbitrary context with no locks held. --*/ { DNS_PROXY_TYPE Type; PROFILE("DnsCleanupProtocol"); if (DnsServerList[DnsProxyDns]) { NH_FREE(DnsServerList[DnsProxyDns]); DnsServerList[DnsProxyDns] = NULL; } if (DnsServerList[DnsProxyWins]) { NH_FREE(DnsServerList[DnsProxyWins]); DnsServerList[DnsProxyWins] = NULL; } if (DnsICSDomainSuffix) { NH_FREE(DnsICSDomainSuffix); DnsICSDomainSuffix = NULL; } if (DnsGlobalInfo) { NH_FREE(DnsGlobalInfo); DnsGlobalInfo = NULL; } InterlockedExchange(reinterpret_cast(&DnsProtocolStopped), 1); SetEvent(DnsNotificationEvent); ResetComponentReference(&DnsComponentReference); NhStopEventLog(); } // DnsCleanupProtocol BOOLEAN DnsInitializeModule( VOID ) /*++ Routine Description: This routine is invoked to initialize the DNS module. Arguments: none. Return Value: BOOLEAN - TRUE if initialization succeeded, FALSE otherwise Environment: Invoked in the context of a 'DllMain' routine on 'DLL_PROCESS_ATTACH'. --*/ { if (InitializeComponentReference( &DnsComponentReference, DnsCleanupProtocol )) { return FALSE; } __try { InitializeCriticalSection(&DnsGlobalInfoLock); } __except(EXCEPTION_EXECUTE_HANDLER) { DeleteComponentReference(&DnsComponentReference); return FALSE; } if (DnsInitializeFileManagement()) { DeleteCriticalSection(&DnsGlobalInfoLock); DeleteComponentReference(&DnsComponentReference); return FALSE; } if (DnsInitializeTableManagement()) { DnsShutdownFileManagement(); DeleteCriticalSection(&DnsGlobalInfoLock); DeleteComponentReference(&DnsComponentReference); return FALSE; } if (DnsInitializeInterfaceManagement()) { DnsShutdownTableManagement(); DnsShutdownFileManagement(); DeleteCriticalSection(&DnsGlobalInfoLock); DeleteComponentReference(&DnsComponentReference); return FALSE; } return TRUE; } // DnsInitializeModule BOOLEAN DnsIsDnsEnabled( VOID ) /*++ Routine Description: This routine is invoked to determine whether the DNS proxy is enabled. It checks the global info which, if found, indicates that the protocol is enabled. Note that the global info critical section is always initialized in the 'DllMain' routine, which is why this routine works if the DNS proxy is not even installed. Arguments: none. Return Value: BOOLEAN - TRUE if DNS proxy is enabled, FALSE otherwise. Environment: Invoked from an arbitrary context. --*/ { PROFILE("DnsIsDnsEnabled"); if (!REFERENCE_DNS()) { return FALSE; } EnterCriticalSection(&DnsGlobalInfoLock); if (!DnsGlobalInfo || !(DnsGlobalInfo->Flags & IP_DNS_PROXY_FLAG_ENABLE_DNS)) { LeaveCriticalSection(&DnsGlobalInfoLock); DEREFERENCE_DNS_AND_RETURN(FALSE); } LeaveCriticalSection(&DnsGlobalInfoLock); DEREFERENCE_DNS_AND_RETURN(TRUE); } // DnsIsDnsEnabled BOOLEAN DnsIsWinsEnabled( VOID ) /*++ Routine Description: This routine is invoked to determine whether the WINS proxy is enabled. It checks the global info which, if found, indicates that the protocol is enabled. Note that the global info critical section is always initialized in the 'DllMain' routine, which is why this routine works if the DNS proxy is not even installed. Arguments: none. Return Value: BOOLEAN - TRUE if WINS proxy is enabled, FALSE otherwise. Environment: Invoked from an arbitrary context. --*/ { PROFILE("DnsIsWinsEnabled"); return FALSE; } // DnsIsWinsEnabled BOOL IsServiceRunning(LPCTSTR pSvcName) { BOOL bRet = FALSE; SERVICE_STATUS Status; SC_HANDLE hService, hScm; hScm = OpenSCManager(NULL, NULL, GENERIC_READ); if (hScm) { hService = OpenService(hScm, pSvcName, SERVICE_QUERY_STATUS); if (hService) { ZeroMemory(&Status, sizeof(Status)); if (QueryServiceStatus(hService, &Status) && (SERVICE_STOPPED != Status.dwCurrentState && SERVICE_STOP_PENDING != Status.dwCurrentState)) { bRet = TRUE; } CloseServiceHandle(hService); } CloseServiceHandle(hScm); } return bRet; } ULONG APIENTRY DnsRmStartProtocol( HANDLE NotificationEvent, PSUPPORT_FUNCTIONS SupportFunctions, PVOID GlobalInfo, ULONG StructureVersion, ULONG StructureSize, ULONG StructureCount ) /*++ Routine Description: This routine is invoked to indicate the component's operation should begin. Arguments: NotificationEvent - event on which we notify the router-manager about asynchronous occurrences SupportFunctions - functions for initiating router-related operations GlobalInfo - configuration for the component Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error = NO_ERROR; SOCKET GlobalSocket; ULONG Size; NTSTATUS status; PROFILE("DnsRmStartProtocol"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); if (!GlobalInfo) { DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER); } NhStartEventLog(); do { // // Copy the global configuration // EnterCriticalSection(&DnsGlobalInfoLock); Size = sizeof(*DnsGlobalInfo); DnsGlobalInfo = reinterpret_cast(NH_ALLOCATE(Size)); if (!DnsGlobalInfo) { LeaveCriticalSection(&DnsGlobalInfoLock); NhTrace( TRACE_FLAG_INIT, "DnsRmStartProtocol: cannot allocate global info" ); NhErrorLog( IP_DNS_PROXY_LOG_ALLOCATION_FAILED, 0, "%d", Size ); Error = ERROR_NOT_ENOUGH_MEMORY; break; } CopyMemory(DnsGlobalInfo, GlobalInfo, Size); // // If a full DNS server is running on this machine // then we need to start DNS Proxy in Disabled mode. // If and when the full DNS server is stopped it will reenable the // Proxy DNS. // if (IsServiceRunning(DNS_SERVICE_NAME)) { DnsGlobalInfo->Flags &= ~IP_DNS_PROXY_FLAG_ENABLE_DNS; } // // Save the notification event // DnsNotificationEvent = NotificationEvent; // // Save the support functions // if (!SupportFunctions) { ZeroMemory(&DnsSupportFunctions, sizeof(DnsSupportFunctions)); } else { CopyMemory( &DnsSupportFunctions, SupportFunctions, sizeof(*SupportFunctions) ); } // // Query for ICS domain suffix string // DnsQueryICSDomainSuffix(); // // Build the server list // DnsQueryServerList(); // // Create the global query-socket // Error = NhCreateDatagramSocket(0, 0, &GlobalSocket); if (Error == NO_ERROR) { InterlockedExchangePointer( (PVOID*)&DnsGlobalSocket, (PVOID)GlobalSocket ); } else { NhTrace( TRACE_FLAG_DNS, "DnsRmStartProtocol: error %d creating global socket", Error ); Error = NO_ERROR; } LeaveCriticalSection(&DnsGlobalInfoLock); // // load entries from the hosts.ics file (if present) // LoadHostsIcsFile(TRUE); InterlockedExchange(reinterpret_cast(&DnsProtocolStopped), 0); } while (FALSE); if (NO_ERROR != Error) { NhStopEventLog(); } DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmStartProtocol ULONG APIENTRY DnsRmStartComplete( VOID ) /*++ Routine Description: This routine is invoked when the router has finished adding the initial configuration Arguments: none. Return Value: ULONG - Win32 status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { return NO_ERROR; } // DnsRmStartComplete ULONG APIENTRY DnsRmStopProtocol( VOID ) /*++ Routine Description: This routine is invoked to stop the protocol. Arguments: none. Return Value: ULONG - Win32 status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { SOCKET GlobalSocket; PROFILE("DnsRmStopProtocol"); // // Reference the module to make sure it's running // REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); // // Save any entries present in our tables // SaveHostsIcsFile(TRUE); // // Empty the dns tables to save memory space // DnsEmptyTables(); EnterCriticalSection(&DnsGlobalInfoLock); if (DnsNotifyChangeKeyWaitHandle) { RtlDeregisterWait(DnsNotifyChangeKeyWaitHandle); DnsNotifyChangeKeyWaitHandle = NULL; } if (DnsNotifyChangeKeyEvent) { NtClose(DnsNotifyChangeKeyEvent); DnsNotifyChangeKeyEvent = NULL; DnsNotifyChangeKeyCallbackRoutine(NULL, FALSE); } if (DnsTcpipInterfacesKey) { NtClose(DnsTcpipInterfacesKey); DnsTcpipInterfacesKey = NULL; } if (DnsNotifyChangeAddressWaitHandle) { RtlDeregisterWait(DnsNotifyChangeAddressWaitHandle); DnsNotifyChangeAddressWaitHandle = NULL; } if (DnsNotifyChangeAddressEvent) { if (CancelIPChangeNotify(&DnsNotifyChangeAddressOverlapped)) { if (WAIT_OBJECT_0 != WaitForSingleObject(DnsNotifyChangeAddressEvent, INFINITE)) { NhTrace( TRACE_FLAG_DNS, "DnsRmStopProtocol: error %d while waiting on " "DnsNotifyChangeAddressEvent", GetLastError() ); } } NtClose(DnsNotifyChangeAddressEvent); DnsNotifyChangeAddressEvent = NULL; DnsNotifyChangeAddressCallbackRoutine(NULL, FALSE); } // // ICSDomain // if (DnsNotifyChangeKeyICSDomainWaitHandle) { RtlDeregisterWait(DnsNotifyChangeKeyICSDomainWaitHandle); DnsNotifyChangeKeyICSDomainWaitHandle = NULL; } if (DnsNotifyChangeKeyICSDomainEvent) { NtClose(DnsNotifyChangeKeyICSDomainEvent); DnsNotifyChangeKeyICSDomainEvent = NULL; DnsNotifyChangeKeyICSDomainCallbackRoutine(NULL, FALSE); } if (DnsTcpipParametersKey) { NtClose(DnsTcpipParametersKey); DnsTcpipParametersKey = NULL; } LeaveCriticalSection(&DnsGlobalInfoLock); GlobalSocket = (SOCKET)InterlockedExchangePointer( (PVOID*)&DnsGlobalSocket, (PVOID)INVALID_SOCKET ); NhDeleteDatagramSocket(GlobalSocket); // // Drop the initial reference to cause a cleanup // ReleaseInitialComponentReference(&DnsComponentReference); return DEREFERENCE_DNS() ? NO_ERROR : ERROR_PROTOCOL_STOP_PENDING; } // DnsRmStopProtocol ULONG APIENTRY DnsRmAddInterface( PWCHAR Name, ULONG Index, NET_INTERFACE_TYPE Type, ULONG MediaType, USHORT AccessType, USHORT ConnectionType, PVOID InterfaceInfo, ULONG StructureVersion, ULONG StructureSize, ULONG StructureCount ) /*++ Routine Description: This routine is invoked to add an interface to the component. Arguments: Name - the name of the interface (unused) Index - the index of the interface Type - the type of the interface InterfaceInfo - the configuration information for the interface Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmAddInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsCreateInterface( Index, Type, (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo, NULL ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmAddInterface ULONG APIENTRY DnsRmDeleteInterface( ULONG Index ) /*++ Routine Description: This routine is invoked to delete an interface from the component. Arguments: Index - the index of the interface Return Value: ULONG - Win32 status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmDeleteInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsDeleteInterface( Index ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmDeleteInterface ULONG APIENTRY DnsRmGetEventMessage( OUT ROUTING_PROTOCOL_EVENTS* Event, OUT MESSAGE* Result ) /*++ Routine Description: This routine is invoked to retrieve an event message from the component. The only event message we generate is the 'ROUTER_STOPPED' message. Arguments: Event - receives the generated event Result - receives the associated result Return Value: ULONG - Win32 status code. --*/ { PROFILE("DnsRmGetEventMessage"); if (InterlockedExchange(reinterpret_cast(&DnsProtocolStopped), 0)) { *Event = ROUTER_STOPPED; return NO_ERROR; } return ERROR_NO_MORE_ITEMS; } // DnsRmGetEventMessage ULONG APIENTRY DnsRmGetInterfaceInfo( ULONG Index, PVOID InterfaceInfo, IN OUT PULONG InterfaceInfoSize, IN OUT PULONG StructureVersion, IN OUT PULONG StructureSize, IN OUT PULONG StructureCount ) /*++ Routine Description: This routine is invoked to retrieve the component's per-interface configuration. Arguments: Index - the index of the interface to be queried InterfaceInfo - receives the query results InterfaceInfoSize - receives the amount of data retrieved Return Value: ULONG - Win32 status code. --*/ { ULONG Error; PROFILE("DnsRmGetInterfaceInfo"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsQueryInterface( Index, (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo, InterfaceInfoSize ); *StructureSize = *InterfaceInfoSize; if (StructureCount) {*StructureCount = 1;} DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmGetInterfaceInfo ULONG APIENTRY DnsRmSetInterfaceInfo( ULONG Index, PVOID InterfaceInfo, ULONG StructureVersion, ULONG StructureSize, ULONG StructureCount ) /*++ Routine Description: This routine is invoked to change the component's per-interface configuration. Arguments: Index - the index of the interface to be updated InterfaceInfo - supplies the new configuration Return Value: ULONG - Win32 status code. --*/ { ULONG Error; PROFILE("DnsRmSetInterfaceInfo"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsConfigureInterface( Index, (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmSetInterfaceInfo ULONG APIENTRY DnsRmInterfaceStatus( ULONG Index, BOOL InterfaceActive, ULONG StatusType, PVOID StatusInfo ) /*++ Routine Description: This routine is invoked to bind/unbind, enable/disable an interface Arguments: Index - the interface to be bound InterfaceActive - whether the interface is active StatusType - type of status being changed (bind or enabled) StatusInfo - Info pertaining to the state being changed Return Value: ULONG - Win32 Status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error = NO_ERROR; switch(StatusType) { case RIS_INTERFACE_ADDRESS_CHANGE: { PIP_ADAPTER_BINDING_INFO BindInfo = (PIP_ADAPTER_BINDING_INFO)StatusInfo; if (BindInfo->AddressCount) { Error = DnsRmBindInterface(Index, StatusInfo); } else { Error = DnsRmUnbindInterface(Index); } break; } case RIS_INTERFACE_ENABLED: { Error = DnsRmEnableInterface(Index); break; } case RIS_INTERFACE_DISABLED: { Error = DnsRmDisableInterface(Index); break; } } return Error; } // DnsRmInterfaceStatus ULONG DnsRmBindInterface( ULONG Index, PVOID BindingInfo ) /*++ Routine Description: This routine is invoked to bind an interface to its IP address(es). Arguments: Index - the interface to be bound BindingInfo - the addressing information Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmBindInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsBindInterface( Index, (PIP_ADAPTER_BINDING_INFO)BindingInfo ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmBindInterface ULONG DnsRmUnbindInterface( ULONG Index ) /*++ Routine Description: This routine is invoked to unbind an interface from its IP address(es). Arguments: Index - the interface to be unbound Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmUnbindInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsUnbindInterface( Index ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmUnbindInterface ULONG DnsRmEnableInterface( ULONG Index ) /*++ Routine Description: This routine is invoked to enable operation on an interface. Arguments: Index - the interface to be enabled. Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmEnableInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsEnableInterface( Index ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmEnableInterface ULONG DnsRmDisableInterface( ULONG Index ) /*++ Routine Description: This routine is invoked to disable operation on an interface. Arguments: Index - the interface to be disabled. Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error; PROFILE("DnsRmDisableInterface"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); Error = DnsDisableInterface( Index ); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsRmDisableInterface ULONG DnsEnableSuffixQuery( VOID ) /*++ Routine Description: This routine is invoked to reenable the suffix watch. Arguments: None. Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error = NO_ERROR; PROFILE("DnsEnableSuffixQuery"); // // enable ICSDomain key watch // REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); EnterCriticalSection(&DnsGlobalInfoLock); DnsQueryICSDomainSuffix(); LeaveCriticalSection(&DnsGlobalInfoLock); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsEnableSuffixQuery ULONG DnsDisableSuffixQuery( VOID ) /*++ Routine Description: This routine is invoked to disable the suffix watch. Arguments: None. Return Value: ULONG - Win32 status code. Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Error = NO_ERROR; PROFILE("DnsDisableSuffixQuery"); // // disable ICSDomain key watch for the period we are disabled // REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); EnterCriticalSection(&DnsGlobalInfoLock); if (DnsNotifyChangeKeyICSDomainWaitHandle) { RtlDeregisterWait(DnsNotifyChangeKeyICSDomainWaitHandle); DnsNotifyChangeKeyICSDomainWaitHandle = NULL; } if (DnsNotifyChangeKeyICSDomainEvent) { NtClose(DnsNotifyChangeKeyICSDomainEvent); DnsNotifyChangeKeyICSDomainEvent = NULL; DnsNotifyChangeKeyICSDomainCallbackRoutine(NULL, FALSE); } if (DnsTcpipParametersKey) { NtClose(DnsTcpipParametersKey); DnsTcpipParametersKey = NULL; } if (DnsICSDomainSuffix) { NH_FREE(DnsICSDomainSuffix); DnsICSDomainSuffix = NULL; } LeaveCriticalSection(&DnsGlobalInfoLock); DEREFERENCE_DNS_AND_RETURN(Error); } // DnsDisableSuffixQuery ULONG APIENTRY DnsRmGetGlobalInfo( PVOID GlobalInfo, IN OUT PULONG GlobalInfoSize, IN OUT PULONG StructureVersion, IN OUT PULONG StructureSize, IN OUT PULONG StructureCount ) /*++ Routine Description: This routine is invoked to retrieve the configuration for the component. Arguments: GlobalInfo - receives the configuration GlobalInfoSize - receives the size of the configuration Return Value: ULONG - Win32 status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG Size; PROFILE("DnsRmGetGlobalInfo"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); if (!GlobalInfoSize || (*GlobalInfoSize && !GlobalInfo)) { DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER); } EnterCriticalSection(&DnsGlobalInfoLock); Size = sizeof(*DnsGlobalInfo); if (*GlobalInfoSize < Size) { LeaveCriticalSection(&DnsGlobalInfoLock); *StructureSize = *GlobalInfoSize = Size; if (StructureCount) {*StructureCount = 1;} DEREFERENCE_DNS_AND_RETURN(ERROR_INSUFFICIENT_BUFFER); } CopyMemory(GlobalInfo, DnsGlobalInfo, Size); LeaveCriticalSection(&DnsGlobalInfoLock); *StructureSize = *GlobalInfoSize = Size; if (StructureCount) {*StructureCount = 1;} DEREFERENCE_DNS_AND_RETURN(NO_ERROR); } // DnsRmGetGlobalInfo ULONG APIENTRY DnsRmSetGlobalInfo( PVOID GlobalInfo, ULONG StructureVersion, ULONG StructureSize, ULONG StructureCount ) /*++ Routine Description: This routine is invoked to change the configuration for the component. Arguments: GlobalInfo - the new configuration Return Value: ULONG - Win32 status code Environment: The routine runs in the context of an IP router-manager thread. --*/ { ULONG OldFlags; ULONG NewFlags; PIP_DNS_PROXY_GLOBAL_INFO NewInfo; ULONG Size; PROFILE("DnsRmSetGlobalInfo"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); if (!GlobalInfo) { DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER); } Size = sizeof(*DnsGlobalInfo); NewInfo = reinterpret_cast(NH_ALLOCATE(Size)); if (!NewInfo) { NhTrace( TRACE_FLAG_INIT, "DnsRmSetGlobalInfo: error reallocating global info" ); NhErrorLog( IP_DNS_PROXY_LOG_ALLOCATION_FAILED, 0, "%d", Size ); DEREFERENCE_DNS_AND_RETURN(ERROR_NOT_ENOUGH_MEMORY); } CopyMemory(NewInfo, GlobalInfo, Size); // // If a full DNS server is running on this machine // then we need to keep DNS Proxy in the Disabled mode. // If and when the full DNS server is stopped it will reenable the // Proxy DNS. if (IsServiceRunning(DNS_SERVICE_NAME)) { NewInfo->Flags &= ~IP_DNS_PROXY_FLAG_ENABLE_DNS; } EnterCriticalSection(&DnsGlobalInfoLock); OldFlags = DnsGlobalInfo->Flags; NH_FREE(DnsGlobalInfo); DnsGlobalInfo = NewInfo; NewFlags = DnsGlobalInfo->Flags; LeaveCriticalSection(&DnsGlobalInfoLock); // // See if the enabled state of either DNS or WINS proxy changed. // If so, we need to deactivate and reactivate all interfaces // if ((NewFlags & IP_DNS_PROXY_FLAG_ENABLE_DNS) != (OldFlags & IP_DNS_PROXY_FLAG_ENABLE_DNS)) { DnsReactivateEveryInterface(); } DEREFERENCE_DNS_AND_RETURN(NO_ERROR); } // DnsRmSetGlobalInfo ULONG APIENTRY DnsRmMibCreate( ULONG InputDataSize, PVOID InputData ) { return ERROR_NOT_SUPPORTED; } ULONG APIENTRY DnsRmMibDelete( ULONG InputDataSize, PVOID InputData ) { return ERROR_NOT_SUPPORTED; } ULONG APIENTRY DnsRmMibGet( ULONG InputDataSize, PVOID InputData, OUT PULONG OutputDataSize, OUT PVOID OutputData ) /*++ Routine Description: The DNS proxy only exposes one item to the MIB; its statistics. Arguments: InputDataSize - the MIB query data size InputData - specifies the MIB object to be retrieved OutputDataSize - the MIB response data size OutputData - receives the MIB object retrieved Return Value: ULONG - Win32 status code. --*/ { ULONG Error; PIP_DNS_PROXY_MIB_QUERY Oidp; PROFILE("DnsRmMibGet"); REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE); if (InputDataSize < sizeof(*Oidp) || !InputData || !OutputDataSize) { Error = ERROR_INVALID_PARAMETER; } else { Oidp = (PIP_DNS_PROXY_MIB_QUERY)InputData; switch(Oidp->Oid) { case IP_DNS_PROXY_STATISTICS_OID: { if (*OutputDataSize < sizeof(*Oidp) + sizeof(DnsStatistics)) { *OutputDataSize = sizeof(*Oidp) + sizeof(DnsStatistics); Error = ERROR_INSUFFICIENT_BUFFER; } else if (!OutputData) { Error = ERROR_INVALID_PARAMETER; } else { *OutputDataSize = sizeof(*Oidp) + sizeof(DnsStatistics); Oidp = (PIP_DNS_PROXY_MIB_QUERY)OutputData; Oidp->Oid = IP_DNS_PROXY_STATISTICS_OID; CopyMemory( Oidp->Data, &DnsStatistics, sizeof(DnsStatistics) ); Error = NO_ERROR; } break; } default: { NhTrace( TRACE_FLAG_DNS, "DnsRmMibGet: oid %d invalid", Oidp->Oid ); Error = ERROR_INVALID_PARAMETER; break; } } } DEREFERENCE_DNS_AND_RETURN(Error); } ULONG APIENTRY DnsRmMibSet( ULONG InputDataSize, PVOID InputData ) { return ERROR_NOT_SUPPORTED; } ULONG APIENTRY DnsRmMibGetFirst( ULONG InputDataSize, PVOID InputData, OUT PULONG OutputDataSize, OUT PVOID OutputData ) { return ERROR_NOT_SUPPORTED; } ULONG APIENTRY DnsRmMibGetNext( ULONG InputDataSize, PVOID InputData, OUT PULONG OutputDataSize, OUT PVOID OutputData ) { return ERROR_NOT_SUPPORTED; }