xref: /aosp_15_r20/external/mdnsresponder/mDNSWindows/SystemService/Service.c (revision 48a54d368dc4fa860885eef7b70b6c53499e7c25)
1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker  *
3*48a54d36SAndroid Build Coastguard Worker  * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker  *
5*48a54d36SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*48a54d36SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*48a54d36SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*48a54d36SAndroid Build Coastguard Worker  *
9*48a54d36SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*48a54d36SAndroid Build Coastguard Worker  *
11*48a54d36SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*48a54d36SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*48a54d36SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*48a54d36SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*48a54d36SAndroid Build Coastguard Worker  * limitations under the License.
16*48a54d36SAndroid Build Coastguard Worker  */
17*48a54d36SAndroid Build Coastguard Worker 
18*48a54d36SAndroid Build Coastguard Worker #include	<stdio.h>
19*48a54d36SAndroid Build Coastguard Worker #include	<stdlib.h>
20*48a54d36SAndroid Build Coastguard Worker #include	<crtdbg.h>
21*48a54d36SAndroid Build Coastguard Worker #include	<stdarg.h>
22*48a54d36SAndroid Build Coastguard Worker #include	<stddef.h>
23*48a54d36SAndroid Build Coastguard Worker 
24*48a54d36SAndroid Build Coastguard Worker 
25*48a54d36SAndroid Build Coastguard Worker #include	"CommonServices.h"
26*48a54d36SAndroid Build Coastguard Worker #include	"DebugServices.h"
27*48a54d36SAndroid Build Coastguard Worker #include	"RegNames.h"
28*48a54d36SAndroid Build Coastguard Worker 
29*48a54d36SAndroid Build Coastguard Worker #include	"uds_daemon.h"
30*48a54d36SAndroid Build Coastguard Worker #include	"GenLinkedList.h"
31*48a54d36SAndroid Build Coastguard Worker #include	"Service.h"
32*48a54d36SAndroid Build Coastguard Worker #include	"mDNSWindows/SystemService/EventLog.h"
33*48a54d36SAndroid Build Coastguard Worker 
34*48a54d36SAndroid Build Coastguard Worker #include	"Resource.h"
35*48a54d36SAndroid Build Coastguard Worker 
36*48a54d36SAndroid Build Coastguard Worker #include	"mDNSEmbeddedAPI.h"
37*48a54d36SAndroid Build Coastguard Worker #include	"uDNS.h"
38*48a54d36SAndroid Build Coastguard Worker #include	"mDNSWin32.h"
39*48a54d36SAndroid Build Coastguard Worker 
40*48a54d36SAndroid Build Coastguard Worker #include	"Firewall.h"
41*48a54d36SAndroid Build Coastguard Worker 
42*48a54d36SAndroid Build Coastguard Worker #if( !TARGET_OS_WINDOWS_CE )
43*48a54d36SAndroid Build Coastguard Worker 	#include	<mswsock.h>
44*48a54d36SAndroid Build Coastguard Worker 	#include	<process.h>
45*48a54d36SAndroid Build Coastguard Worker 	#include	<ipExport.h>
46*48a54d36SAndroid Build Coastguard Worker 	#include	<ws2def.h>
47*48a54d36SAndroid Build Coastguard Worker 	#include	<ws2ipdef.h>
48*48a54d36SAndroid Build Coastguard Worker 	#include	<iphlpapi.h>
49*48a54d36SAndroid Build Coastguard Worker 	#include	<netioapi.h>
50*48a54d36SAndroid Build Coastguard Worker 	#include	<iptypes.h>
51*48a54d36SAndroid Build Coastguard Worker 	#include	<powrprof.h>
52*48a54d36SAndroid Build Coastguard Worker #endif
53*48a54d36SAndroid Build Coastguard Worker 
54*48a54d36SAndroid Build Coastguard Worker #ifndef HeapEnableTerminationOnCorruption
55*48a54d36SAndroid Build Coastguard Worker #	define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
56*48a54d36SAndroid Build Coastguard Worker #endif
57*48a54d36SAndroid Build Coastguard Worker 
58*48a54d36SAndroid Build Coastguard Worker #if 0
59*48a54d36SAndroid Build Coastguard Worker #pragma mark == Constants ==
60*48a54d36SAndroid Build Coastguard Worker #endif
61*48a54d36SAndroid Build Coastguard Worker 
62*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
63*48a54d36SAndroid Build Coastguard Worker //	Constants
64*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
65*48a54d36SAndroid Build Coastguard Worker 
66*48a54d36SAndroid Build Coastguard Worker #define	DEBUG_NAME							"[mDNSWin32] "
67*48a54d36SAndroid Build Coastguard Worker #define kServiceFirewallName				L"Bonjour"
68*48a54d36SAndroid Build Coastguard Worker #define	kServiceDependencies				TEXT("Tcpip\0\0")
69*48a54d36SAndroid Build Coastguard Worker #define	kDNSServiceCacheEntryCountDefault	512
70*48a54d36SAndroid Build Coastguard Worker #define kRetryFirewallPeriod				30 * 1000
71*48a54d36SAndroid Build Coastguard Worker #define kDefValueSize						MAX_PATH + 1
72*48a54d36SAndroid Build Coastguard Worker #define kZeroIndex							0
73*48a54d36SAndroid Build Coastguard Worker #define kDefaultRouteMetric					399
74*48a54d36SAndroid Build Coastguard Worker #define kSecondsTo100NSUnits				( 10 * 1000 * 1000 )
75*48a54d36SAndroid Build Coastguard Worker #define kSPSMaintenanceWakePeriod			-30
76*48a54d36SAndroid Build Coastguard Worker 
77*48a54d36SAndroid Build Coastguard Worker #define RR_CACHE_SIZE 500
78*48a54d36SAndroid Build Coastguard Worker static CacheEntity gRRCache[RR_CACHE_SIZE];
79*48a54d36SAndroid Build Coastguard Worker #if 0
80*48a54d36SAndroid Build Coastguard Worker #pragma mark == Structures ==
81*48a54d36SAndroid Build Coastguard Worker #endif
82*48a54d36SAndroid Build Coastguard Worker 
83*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
84*48a54d36SAndroid Build Coastguard Worker //	Structures
85*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
86*48a54d36SAndroid Build Coastguard Worker 
87*48a54d36SAndroid Build Coastguard Worker typedef struct EventSource
88*48a54d36SAndroid Build Coastguard Worker {
89*48a54d36SAndroid Build Coastguard Worker 	HANDLE							event;
90*48a54d36SAndroid Build Coastguard Worker 	void						*	context;
91*48a54d36SAndroid Build Coastguard Worker 	RegisterWaitableEventHandler	handler;
92*48a54d36SAndroid Build Coastguard Worker 	struct EventSource			*	next;
93*48a54d36SAndroid Build Coastguard Worker } EventSource;
94*48a54d36SAndroid Build Coastguard Worker 
95*48a54d36SAndroid Build Coastguard Worker static BOOL											gEventSourceListChanged = FALSE;
96*48a54d36SAndroid Build Coastguard Worker static EventSource								*	gEventSourceList = NULL;
97*48a54d36SAndroid Build Coastguard Worker static EventSource								*	gCurrentSource = NULL;
98*48a54d36SAndroid Build Coastguard Worker static int											gEventSources = 0;
99*48a54d36SAndroid Build Coastguard Worker 
100*48a54d36SAndroid Build Coastguard Worker #define	kWaitListStopEvent							( WAIT_OBJECT_0 + 0 )
101*48a54d36SAndroid Build Coastguard Worker #define	kWaitListInterfaceListChangedEvent			( WAIT_OBJECT_0 + 1 )
102*48a54d36SAndroid Build Coastguard Worker #define kWaitListComputerDescriptionEvent			( WAIT_OBJECT_0 + 2 )
103*48a54d36SAndroid Build Coastguard Worker #define kWaitListTCPIPEvent							( WAIT_OBJECT_0 + 3 )
104*48a54d36SAndroid Build Coastguard Worker #define kWaitListDynDNSEvent						( WAIT_OBJECT_0 + 4 )
105*48a54d36SAndroid Build Coastguard Worker #define kWaitListFileShareEvent						( WAIT_OBJECT_0 + 5 )
106*48a54d36SAndroid Build Coastguard Worker #define kWaitListFirewallEvent						( WAIT_OBJECT_0 + 6 )
107*48a54d36SAndroid Build Coastguard Worker #define kWaitListAdvertisedServicesEvent			( WAIT_OBJECT_0 + 7 )
108*48a54d36SAndroid Build Coastguard Worker #define kWaitListSPSWakeupEvent						( WAIT_OBJECT_0 + 8 )
109*48a54d36SAndroid Build Coastguard Worker #define kWaitListSPSSleepEvent						( WAIT_OBJECT_0 + 9 )
110*48a54d36SAndroid Build Coastguard Worker #define	kWaitListFixedItemCount						10
111*48a54d36SAndroid Build Coastguard Worker 
112*48a54d36SAndroid Build Coastguard Worker 
113*48a54d36SAndroid Build Coastguard Worker #if 0
114*48a54d36SAndroid Build Coastguard Worker #pragma mark == Prototypes ==
115*48a54d36SAndroid Build Coastguard Worker #endif
116*48a54d36SAndroid Build Coastguard Worker 
117*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
118*48a54d36SAndroid Build Coastguard Worker //	Prototypes
119*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
120*48a54d36SAndroid Build Coastguard Worker static void			Usage( void );
121*48a54d36SAndroid Build Coastguard Worker static BOOL WINAPI	ConsoleControlHandler( DWORD inControlEvent );
122*48a54d36SAndroid Build Coastguard Worker static OSStatus		InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath );
123*48a54d36SAndroid Build Coastguard Worker static OSStatus		RemoveService( LPCTSTR inName );
124*48a54d36SAndroid Build Coastguard Worker static OSStatus		SetServiceParameters();
125*48a54d36SAndroid Build Coastguard Worker static OSStatus		GetServiceParameters();
126*48a54d36SAndroid Build Coastguard Worker static OSStatus		CheckFirewall();
127*48a54d36SAndroid Build Coastguard Worker static OSStatus		SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription );
128*48a54d36SAndroid Build Coastguard Worker static void			ReportStatus( int inType, const char *inFormat, ... );
129*48a54d36SAndroid Build Coastguard Worker 
130*48a54d36SAndroid Build Coastguard Worker static void WINAPI	ServiceMain( DWORD argc, LPTSTR argv[] );
131*48a54d36SAndroid Build Coastguard Worker static OSStatus		ServiceSetupEventLogging( void );
132*48a54d36SAndroid Build Coastguard Worker static DWORD WINAPI	ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext );
133*48a54d36SAndroid Build Coastguard Worker 
134*48a54d36SAndroid Build Coastguard Worker static OSStatus		ServiceRun( int argc, LPTSTR argv[] );
135*48a54d36SAndroid Build Coastguard Worker static void			ServiceStop( void );
136*48a54d36SAndroid Build Coastguard Worker 
137*48a54d36SAndroid Build Coastguard Worker static OSStatus		ServiceSpecificInitialize( int argc, LPTSTR  argv[] );
138*48a54d36SAndroid Build Coastguard Worker static OSStatus		ServiceSpecificRun( int argc, LPTSTR argv[] );
139*48a54d36SAndroid Build Coastguard Worker static OSStatus		ServiceSpecificStop( void );
140*48a54d36SAndroid Build Coastguard Worker static void			ServiceSpecificFinalize( int argc, LPTSTR argv[] );
141*48a54d36SAndroid Build Coastguard Worker static mStatus		SetupNotifications();
142*48a54d36SAndroid Build Coastguard Worker static mStatus		TearDownNotifications();
143*48a54d36SAndroid Build Coastguard Worker static mStatus		RegisterWaitableEvent( mDNS * const inMDNS, HANDLE event, void * context, RegisterWaitableEventHandler handler );
144*48a54d36SAndroid Build Coastguard Worker static void			UnregisterWaitableEvent( mDNS * const inMDNS, HANDLE event );
145*48a54d36SAndroid Build Coastguard Worker static mStatus		SetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount );
146*48a54d36SAndroid Build Coastguard Worker static void			UDSCanAccept( mDNS * const inMDNS, HANDLE event, void * context );
147*48a54d36SAndroid Build Coastguard Worker static void			UDSCanRead( TCPSocket * sock );
148*48a54d36SAndroid Build Coastguard Worker static void			HandlePowerSuspend( void * v );
149*48a54d36SAndroid Build Coastguard Worker static void			HandlePowerResumeSuspend( void * v );
150*48a54d36SAndroid Build Coastguard Worker static void			CoreCallback(mDNS * const inMDNS, mStatus result);
151*48a54d36SAndroid Build Coastguard Worker static mDNSu8		SystemWakeForNetworkAccess( LARGE_INTEGER * timeout );
152*48a54d36SAndroid Build Coastguard Worker static OSStatus		GetRouteDestination(DWORD * ifIndex, DWORD * address);
153*48a54d36SAndroid Build Coastguard Worker static OSStatus		SetLLRoute( mDNS * const inMDNS );
154*48a54d36SAndroid Build Coastguard Worker static bool			HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric );
155*48a54d36SAndroid Build Coastguard Worker static bool			IsValidAddress( const char * addr );
156*48a54d36SAndroid Build Coastguard Worker static bool			IsNortelVPN( IP_ADAPTER_INFO * pAdapter );
157*48a54d36SAndroid Build Coastguard Worker static bool			IsJuniperVPN( IP_ADAPTER_INFO * pAdapter );
158*48a54d36SAndroid Build Coastguard Worker static bool			IsCiscoVPN( IP_ADAPTER_INFO * pAdapter );
159*48a54d36SAndroid Build Coastguard Worker static const char * strnistr( const char * string, const char * subString, size_t max );
160*48a54d36SAndroid Build Coastguard Worker 
161*48a54d36SAndroid Build Coastguard Worker #if defined(UNICODE)
162*48a54d36SAndroid Build Coastguard Worker #	define StrLen(X)	wcslen(X)
163*48a54d36SAndroid Build Coastguard Worker #	define StrCmp(X,Y)	wcscmp(X,Y)
164*48a54d36SAndroid Build Coastguard Worker #else
165*48a54d36SAndroid Build Coastguard Worker #	define StrLen(X)	strlen(X)
166*48a54d36SAndroid Build Coastguard Worker #	define StrCmp(X,Y)	strcmp(X,Y)
167*48a54d36SAndroid Build Coastguard Worker #endif
168*48a54d36SAndroid Build Coastguard Worker 
169*48a54d36SAndroid Build Coastguard Worker 
170*48a54d36SAndroid Build Coastguard Worker #define kLLNetworkAddr      "169.254.0.0"
171*48a54d36SAndroid Build Coastguard Worker #define kLLNetworkAddrMask  "255.255.0.0"
172*48a54d36SAndroid Build Coastguard Worker 
173*48a54d36SAndroid Build Coastguard Worker 
174*48a54d36SAndroid Build Coastguard Worker #include	"mDNSEmbeddedAPI.h"
175*48a54d36SAndroid Build Coastguard Worker 
176*48a54d36SAndroid Build Coastguard Worker #if 0
177*48a54d36SAndroid Build Coastguard Worker #pragma mark == Globals ==
178*48a54d36SAndroid Build Coastguard Worker #endif
179*48a54d36SAndroid Build Coastguard Worker 
180*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
181*48a54d36SAndroid Build Coastguard Worker //	Globals
182*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
183*48a54d36SAndroid Build Coastguard Worker #define gMDNSRecord mDNSStorage
184*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL	mDNS_PlatformSupport		gPlatformStorage;
185*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL BOOL						gServiceQuietMode		= FALSE;
186*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL SERVICE_TABLE_ENTRY			gServiceDispatchTable[] =
187*48a54d36SAndroid Build Coastguard Worker {
188*48a54d36SAndroid Build Coastguard Worker 	{ kServiceName,	ServiceMain },
189*48a54d36SAndroid Build Coastguard Worker 	{ NULL, 		NULL }
190*48a54d36SAndroid Build Coastguard Worker };
191*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL SOCKET						gInterfaceListChangedSocket	= INVALID_SOCKET;
192*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gInterfaceListChangedEvent	= NULL;
193*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gDescKey					= NULL;
194*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gDescChangedEvent			= NULL;	// Computer description changed event
195*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gTcpipKey					= NULL;
196*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gTcpipChangedEvent			= NULL;	// TCP/IP config changed
197*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gDdnsKey					= NULL;
198*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gDdnsChangedEvent			= NULL;	// DynDNS config changed
199*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gFileSharingKey				= NULL;
200*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gFileSharingChangedEvent	= NULL;	// File Sharing changed
201*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gFirewallKey				= NULL;
202*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gFirewallChangedEvent		= NULL;	// Firewall changed
203*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HKEY						gAdvertisedServicesKey		= NULL;
204*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gAdvertisedServicesChangedEvent	= NULL; // Advertised services changed
205*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL SERVICE_STATUS				gServiceStatus;
206*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL SERVICE_STATUS_HANDLE		gServiceStatusHandle 	= NULL;
207*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gServiceEventSource		= NULL;
208*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL bool						gServiceAllowRemote		= false;
209*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL int							gServiceCacheEntryCount	= 0;	// 0 means to use the DNS-SD default.
210*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL bool						gServiceManageLLRouting = true;
211*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL int							gWaitCount				= 0;
212*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE					*	gWaitList				= NULL;
213*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gStopEvent				= NULL;
214*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gSPSWakeupEvent			= NULL;
215*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gSPSSleepEvent			= NULL;
216*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL HANDLE						gUDSEvent				= NULL;
217*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL SocketRef					gUDSSocket				= 0;
218*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL udsEventCallback			gUDSCallback			= NULL;
219*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL BOOL						gRetryFirewall			= FALSE;
220*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL DWORD						gOSMajorVersion;
221*48a54d36SAndroid Build Coastguard Worker DEBUG_LOCAL DWORD						gOSMinorVersion;
222*48a54d36SAndroid Build Coastguard Worker 
223*48a54d36SAndroid Build Coastguard Worker typedef DWORD ( WINAPI * GetIpInterfaceEntryFunctionPtr )( PMIB_IPINTERFACE_ROW );
224*48a54d36SAndroid Build Coastguard Worker mDNSlocal HMODULE								gIPHelperLibraryInstance		= NULL;
225*48a54d36SAndroid Build Coastguard Worker mDNSlocal GetIpInterfaceEntryFunctionPtr		gGetIpInterfaceEntryFunctionPtr	= NULL;
226*48a54d36SAndroid Build Coastguard Worker 
227*48a54d36SAndroid Build Coastguard Worker 
228*48a54d36SAndroid Build Coastguard Worker #if 0
229*48a54d36SAndroid Build Coastguard Worker #pragma mark -
230*48a54d36SAndroid Build Coastguard Worker #endif
231*48a54d36SAndroid Build Coastguard Worker 
232*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
233*48a54d36SAndroid Build Coastguard Worker //	Main
234*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
Main(int argc,LPTSTR argv[])235*48a54d36SAndroid Build Coastguard Worker int	Main( int argc, LPTSTR argv[] )
236*48a54d36SAndroid Build Coastguard Worker {
237*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
238*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
239*48a54d36SAndroid Build Coastguard Worker 	BOOL			start;
240*48a54d36SAndroid Build Coastguard Worker 	int				i;
241*48a54d36SAndroid Build Coastguard Worker 
242*48a54d36SAndroid Build Coastguard Worker 	HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
243*48a54d36SAndroid Build Coastguard Worker 
244*48a54d36SAndroid Build Coastguard Worker 	debug_initialize( kDebugOutputTypeMetaConsole );
245*48a54d36SAndroid Build Coastguard Worker 	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
246*48a54d36SAndroid Build Coastguard Worker 
247*48a54d36SAndroid Build Coastguard Worker 	// Default to automatically starting the service dispatcher if no extra arguments are specified.
248*48a54d36SAndroid Build Coastguard Worker 
249*48a54d36SAndroid Build Coastguard Worker 	start = ( argc <= 1 );
250*48a54d36SAndroid Build Coastguard Worker 
251*48a54d36SAndroid Build Coastguard Worker 	// Parse arguments.
252*48a54d36SAndroid Build Coastguard Worker 
253*48a54d36SAndroid Build Coastguard Worker 	for( i = 1; i < argc; ++i )
254*48a54d36SAndroid Build Coastguard Worker 	{
255*48a54d36SAndroid Build Coastguard Worker 		if( StrCmp( argv[ i ], TEXT("-install") ) == 0 )			// Install
256*48a54d36SAndroid Build Coastguard Worker 		{
257*48a54d36SAndroid Build Coastguard Worker 			TCHAR desc[ 256 ];
258*48a54d36SAndroid Build Coastguard Worker 
259*48a54d36SAndroid Build Coastguard Worker 			desc[ 0 ] = 0;
260*48a54d36SAndroid Build Coastguard Worker 			LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
261*48a54d36SAndroid Build Coastguard Worker 			err = InstallService( kServiceName, kServiceName, desc, argv[0] );
262*48a54d36SAndroid Build Coastguard Worker 			if( err )
263*48a54d36SAndroid Build Coastguard Worker 			{
264*48a54d36SAndroid Build Coastguard Worker 				ReportStatus( EVENTLOG_ERROR_TYPE, "install service failed (%d)\n", err );
265*48a54d36SAndroid Build Coastguard Worker 				goto exit;
266*48a54d36SAndroid Build Coastguard Worker 			}
267*48a54d36SAndroid Build Coastguard Worker 		}
268*48a54d36SAndroid Build Coastguard Worker 		else if( StrCmp( argv[ i ], TEXT("-remove") ) == 0 )		// Remove
269*48a54d36SAndroid Build Coastguard Worker 		{
270*48a54d36SAndroid Build Coastguard Worker 			err = RemoveService( kServiceName );
271*48a54d36SAndroid Build Coastguard Worker 			if( err )
272*48a54d36SAndroid Build Coastguard Worker 			{
273*48a54d36SAndroid Build Coastguard Worker 				ReportStatus( EVENTLOG_ERROR_TYPE, "remove service failed (%d)\n", err );
274*48a54d36SAndroid Build Coastguard Worker 				goto exit;
275*48a54d36SAndroid Build Coastguard Worker 			}
276*48a54d36SAndroid Build Coastguard Worker 		}
277*48a54d36SAndroid Build Coastguard Worker 		else if( StrCmp( argv[ i ], TEXT("-start") ) == 0 )		// Start
278*48a54d36SAndroid Build Coastguard Worker 		{
279*48a54d36SAndroid Build Coastguard Worker 			start = TRUE;
280*48a54d36SAndroid Build Coastguard Worker 		}
281*48a54d36SAndroid Build Coastguard Worker 		else if( StrCmp( argv[ i ], TEXT("-server") ) == 0 )		// Server
282*48a54d36SAndroid Build Coastguard Worker 		{
283*48a54d36SAndroid Build Coastguard Worker 			err = RunDirect( argc, argv );
284*48a54d36SAndroid Build Coastguard Worker 			if( err )
285*48a54d36SAndroid Build Coastguard Worker 			{
286*48a54d36SAndroid Build Coastguard Worker 				ReportStatus( EVENTLOG_ERROR_TYPE, "run service directly failed (%d)\n", err );
287*48a54d36SAndroid Build Coastguard Worker 			}
288*48a54d36SAndroid Build Coastguard Worker 			goto exit;
289*48a54d36SAndroid Build Coastguard Worker 		}
290*48a54d36SAndroid Build Coastguard Worker 		else if( StrCmp( argv[ i ], TEXT("-q") ) == 0 )			// Quiet Mode (toggle)
291*48a54d36SAndroid Build Coastguard Worker 		{
292*48a54d36SAndroid Build Coastguard Worker 			gServiceQuietMode = !gServiceQuietMode;
293*48a54d36SAndroid Build Coastguard Worker 		}
294*48a54d36SAndroid Build Coastguard Worker 		else if( ( StrCmp( argv[ i ], TEXT("-help") ) == 0 ) || 	// Help
295*48a54d36SAndroid Build Coastguard Worker 				 ( StrCmp( argv[ i ], TEXT("-h") ) == 0 ) )
296*48a54d36SAndroid Build Coastguard Worker 		{
297*48a54d36SAndroid Build Coastguard Worker 			Usage();
298*48a54d36SAndroid Build Coastguard Worker 			err = 0;
299*48a54d36SAndroid Build Coastguard Worker 			break;
300*48a54d36SAndroid Build Coastguard Worker 		}
301*48a54d36SAndroid Build Coastguard Worker 		else
302*48a54d36SAndroid Build Coastguard Worker 		{
303*48a54d36SAndroid Build Coastguard Worker 			Usage();
304*48a54d36SAndroid Build Coastguard Worker 			err = kParamErr;
305*48a54d36SAndroid Build Coastguard Worker 			break;
306*48a54d36SAndroid Build Coastguard Worker 		}
307*48a54d36SAndroid Build Coastguard Worker 	}
308*48a54d36SAndroid Build Coastguard Worker 
309*48a54d36SAndroid Build Coastguard Worker 	// Start the service dispatcher if requested. This does not return until all services have terminated. If any
310*48a54d36SAndroid Build Coastguard Worker 	// global initialization is needed, it should be done before starting the service dispatcher, but only if it
311*48a54d36SAndroid Build Coastguard Worker 	// will take less than 30 seconds. Otherwise, use a separate thread for it and start the dispatcher immediately.
312*48a54d36SAndroid Build Coastguard Worker 
313*48a54d36SAndroid Build Coastguard Worker 	if( start )
314*48a54d36SAndroid Build Coastguard Worker 	{
315*48a54d36SAndroid Build Coastguard Worker 		ok = StartServiceCtrlDispatcher( gServiceDispatchTable );
316*48a54d36SAndroid Build Coastguard Worker 		err = translate_errno( ok, (OSStatus) GetLastError(), kInUseErr );
317*48a54d36SAndroid Build Coastguard Worker 		if( err != kNoErr )
318*48a54d36SAndroid Build Coastguard Worker 		{
319*48a54d36SAndroid Build Coastguard Worker 			ReportStatus( EVENTLOG_ERROR_TYPE, "start service dispatcher failed (%d)\n", err );
320*48a54d36SAndroid Build Coastguard Worker 			goto exit;
321*48a54d36SAndroid Build Coastguard Worker 		}
322*48a54d36SAndroid Build Coastguard Worker 	}
323*48a54d36SAndroid Build Coastguard Worker 	err = 0;
324*48a54d36SAndroid Build Coastguard Worker 
325*48a54d36SAndroid Build Coastguard Worker exit:
326*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelTrace, DEBUG_NAME "exited (%d %m)\n", err, err );
327*48a54d36SAndroid Build Coastguard Worker 	_CrtDumpMemoryLeaks();
328*48a54d36SAndroid Build Coastguard Worker 	return( (int) err );
329*48a54d36SAndroid Build Coastguard Worker }
330*48a54d36SAndroid Build Coastguard Worker 
331*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
332*48a54d36SAndroid Build Coastguard Worker //	Usage
333*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
334*48a54d36SAndroid Build Coastguard Worker 
Usage(void)335*48a54d36SAndroid Build Coastguard Worker static void	Usage( void )
336*48a54d36SAndroid Build Coastguard Worker {
337*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "\n" );
338*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "mDNSResponder 1.0d1\n" );
339*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "\n" );
340*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    <no args>    Runs the service normally\n" );
341*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -install     Creates the service and starts it\n" );
342*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -remove      Stops the service and deletes it\n" );
343*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -start       Starts the service dispatcher after processing all other arguments\n" );
344*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -server      Runs the service directly as a server (for debugging)\n" );
345*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -q           Toggles Quiet Mode (no events or output)\n" );
346*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -remote      Allow remote connections\n" );
347*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -cache n     Number of mDNS cache entries (defaults to %d)\n", kDNSServiceCacheEntryCountDefault );
348*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "    -h[elp]      Display Help/Usage\n" );
349*48a54d36SAndroid Build Coastguard Worker 	fprintf( stderr, "\n" );
350*48a54d36SAndroid Build Coastguard Worker }
351*48a54d36SAndroid Build Coastguard Worker 
352*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
353*48a54d36SAndroid Build Coastguard Worker //	ConsoleControlHandler
354*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
355*48a54d36SAndroid Build Coastguard Worker 
ConsoleControlHandler(DWORD inControlEvent)356*48a54d36SAndroid Build Coastguard Worker static BOOL WINAPI	ConsoleControlHandler( DWORD inControlEvent )
357*48a54d36SAndroid Build Coastguard Worker {
358*48a54d36SAndroid Build Coastguard Worker 	BOOL			handled;
359*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
360*48a54d36SAndroid Build Coastguard Worker 
361*48a54d36SAndroid Build Coastguard Worker 	handled = FALSE;
362*48a54d36SAndroid Build Coastguard Worker 	switch( inControlEvent )
363*48a54d36SAndroid Build Coastguard Worker 	{
364*48a54d36SAndroid Build Coastguard Worker 		case CTRL_C_EVENT:
365*48a54d36SAndroid Build Coastguard Worker 		case CTRL_BREAK_EVENT:
366*48a54d36SAndroid Build Coastguard Worker 		case CTRL_CLOSE_EVENT:
367*48a54d36SAndroid Build Coastguard Worker 		case CTRL_LOGOFF_EVENT:
368*48a54d36SAndroid Build Coastguard Worker 		case CTRL_SHUTDOWN_EVENT:
369*48a54d36SAndroid Build Coastguard Worker 			err = ServiceSpecificStop();
370*48a54d36SAndroid Build Coastguard Worker 			require_noerr( err, exit );
371*48a54d36SAndroid Build Coastguard Worker 
372*48a54d36SAndroid Build Coastguard Worker 			handled = TRUE;
373*48a54d36SAndroid Build Coastguard Worker 			break;
374*48a54d36SAndroid Build Coastguard Worker 
375*48a54d36SAndroid Build Coastguard Worker 		default:
376*48a54d36SAndroid Build Coastguard Worker 			break;
377*48a54d36SAndroid Build Coastguard Worker 	}
378*48a54d36SAndroid Build Coastguard Worker 
379*48a54d36SAndroid Build Coastguard Worker exit:
380*48a54d36SAndroid Build Coastguard Worker 	return( handled );
381*48a54d36SAndroid Build Coastguard Worker }
382*48a54d36SAndroid Build Coastguard Worker 
383*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
384*48a54d36SAndroid Build Coastguard Worker //	InstallService
385*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
386*48a54d36SAndroid Build Coastguard Worker 
InstallService(LPCTSTR inName,LPCTSTR inDisplayName,LPCTSTR inDescription,LPCTSTR inPath)387*48a54d36SAndroid Build Coastguard Worker static OSStatus	InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath )
388*48a54d36SAndroid Build Coastguard Worker {
389*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
390*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE		scm;
391*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE		service;
392*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
393*48a54d36SAndroid Build Coastguard Worker 	TCHAR			fullPath[ MAX_PATH ];
394*48a54d36SAndroid Build Coastguard Worker 	TCHAR *			namePtr;
395*48a54d36SAndroid Build Coastguard Worker 	DWORD			size;
396*48a54d36SAndroid Build Coastguard Worker 
397*48a54d36SAndroid Build Coastguard Worker 	scm		= NULL;
398*48a54d36SAndroid Build Coastguard Worker 	service = NULL;
399*48a54d36SAndroid Build Coastguard Worker 
400*48a54d36SAndroid Build Coastguard Worker 	// Get a full path to the executable since a relative path may have been specified.
401*48a54d36SAndroid Build Coastguard Worker 
402*48a54d36SAndroid Build Coastguard Worker 	size = GetFullPathName( inPath, MAX_PATH, fullPath, &namePtr );
403*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
404*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
405*48a54d36SAndroid Build Coastguard Worker 
406*48a54d36SAndroid Build Coastguard Worker 	// Create the service and start it.
407*48a54d36SAndroid Build Coastguard Worker 
408*48a54d36SAndroid Build Coastguard Worker 	scm = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
409*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr );
410*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
411*48a54d36SAndroid Build Coastguard Worker 
412*48a54d36SAndroid Build Coastguard Worker 	service = CreateService( scm, inName, inDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_SHARE_PROCESS,
413*48a54d36SAndroid Build Coastguard Worker 							 SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, fullPath, NULL, NULL, kServiceDependencies,
414*48a54d36SAndroid Build Coastguard Worker 							 NULL, NULL );
415*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( service, (OSStatus) GetLastError(), kDuplicateErr );
416*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
417*48a54d36SAndroid Build Coastguard Worker 
418*48a54d36SAndroid Build Coastguard Worker 	err = SetServiceParameters();
419*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
420*48a54d36SAndroid Build Coastguard Worker 
421*48a54d36SAndroid Build Coastguard Worker 	if( inDescription )
422*48a54d36SAndroid Build Coastguard Worker 	{
423*48a54d36SAndroid Build Coastguard Worker 		err = SetServiceInfo( scm, inName, inDescription );
424*48a54d36SAndroid Build Coastguard Worker 		check_noerr( err );
425*48a54d36SAndroid Build Coastguard Worker 	}
426*48a54d36SAndroid Build Coastguard Worker 
427*48a54d36SAndroid Build Coastguard Worker 	ok = StartService( service, 0, NULL );
428*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kInUseErr );
429*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
430*48a54d36SAndroid Build Coastguard Worker 
431*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_SUCCESS, "installed service\n" );
432*48a54d36SAndroid Build Coastguard Worker 	err = kNoErr;
433*48a54d36SAndroid Build Coastguard Worker 
434*48a54d36SAndroid Build Coastguard Worker exit:
435*48a54d36SAndroid Build Coastguard Worker 	if( service )
436*48a54d36SAndroid Build Coastguard Worker 	{
437*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle( service );
438*48a54d36SAndroid Build Coastguard Worker 	}
439*48a54d36SAndroid Build Coastguard Worker 	if( scm )
440*48a54d36SAndroid Build Coastguard Worker 	{
441*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle( scm );
442*48a54d36SAndroid Build Coastguard Worker 	}
443*48a54d36SAndroid Build Coastguard Worker 	return( err );
444*48a54d36SAndroid Build Coastguard Worker }
445*48a54d36SAndroid Build Coastguard Worker 
446*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
447*48a54d36SAndroid Build Coastguard Worker //	RemoveService
448*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
449*48a54d36SAndroid Build Coastguard Worker 
RemoveService(LPCTSTR inName)450*48a54d36SAndroid Build Coastguard Worker static OSStatus	RemoveService( LPCTSTR inName )
451*48a54d36SAndroid Build Coastguard Worker {
452*48a54d36SAndroid Build Coastguard Worker 	OSStatus			err;
453*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE			scm;
454*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE			service;
455*48a54d36SAndroid Build Coastguard Worker 	BOOL				ok;
456*48a54d36SAndroid Build Coastguard Worker 	SERVICE_STATUS		status;
457*48a54d36SAndroid Build Coastguard Worker 
458*48a54d36SAndroid Build Coastguard Worker 	scm		= NULL;
459*48a54d36SAndroid Build Coastguard Worker 	service = NULL;
460*48a54d36SAndroid Build Coastguard Worker 
461*48a54d36SAndroid Build Coastguard Worker 	// Open a connection to the service.
462*48a54d36SAndroid Build Coastguard Worker 
463*48a54d36SAndroid Build Coastguard Worker 	scm = OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
464*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr );
465*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
466*48a54d36SAndroid Build Coastguard Worker 
467*48a54d36SAndroid Build Coastguard Worker 	service = OpenService( scm, inName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE );
468*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr );
469*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
470*48a54d36SAndroid Build Coastguard Worker 
471*48a54d36SAndroid Build Coastguard Worker 	// Stop the service, if it is not already stopped, then delete it.
472*48a54d36SAndroid Build Coastguard Worker 
473*48a54d36SAndroid Build Coastguard Worker 	ok = QueryServiceStatus( service, &status );
474*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr );
475*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
476*48a54d36SAndroid Build Coastguard Worker 
477*48a54d36SAndroid Build Coastguard Worker 	if( status.dwCurrentState != SERVICE_STOPPED )
478*48a54d36SAndroid Build Coastguard Worker 	{
479*48a54d36SAndroid Build Coastguard Worker 		ok = ControlService( service, SERVICE_CONTROL_STOP, &status );
480*48a54d36SAndroid Build Coastguard Worker 		check_translated_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr );
481*48a54d36SAndroid Build Coastguard Worker 	}
482*48a54d36SAndroid Build Coastguard Worker 
483*48a54d36SAndroid Build Coastguard Worker 	ok = DeleteService( service );
484*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kDeletedErr );
485*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
486*48a54d36SAndroid Build Coastguard Worker 
487*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_SUCCESS, "Removed service\n" );
488*48a54d36SAndroid Build Coastguard Worker 	err = ERROR_SUCCESS;
489*48a54d36SAndroid Build Coastguard Worker 
490*48a54d36SAndroid Build Coastguard Worker exit:
491*48a54d36SAndroid Build Coastguard Worker 	if( service )
492*48a54d36SAndroid Build Coastguard Worker 	{
493*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle( service );
494*48a54d36SAndroid Build Coastguard Worker 	}
495*48a54d36SAndroid Build Coastguard Worker 	if( scm )
496*48a54d36SAndroid Build Coastguard Worker 	{
497*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle( scm );
498*48a54d36SAndroid Build Coastguard Worker 	}
499*48a54d36SAndroid Build Coastguard Worker 	return( err );
500*48a54d36SAndroid Build Coastguard Worker }
501*48a54d36SAndroid Build Coastguard Worker 
502*48a54d36SAndroid Build Coastguard Worker 
503*48a54d36SAndroid Build Coastguard Worker 
504*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
505*48a54d36SAndroid Build Coastguard Worker //	SetServiceParameters
506*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
507*48a54d36SAndroid Build Coastguard Worker 
SetServiceParameters()508*48a54d36SAndroid Build Coastguard Worker static OSStatus SetServiceParameters()
509*48a54d36SAndroid Build Coastguard Worker {
510*48a54d36SAndroid Build Coastguard Worker 	DWORD 			value;
511*48a54d36SAndroid Build Coastguard Worker 	DWORD			valueLen = sizeof(DWORD);
512*48a54d36SAndroid Build Coastguard Worker 	DWORD			type;
513*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
514*48a54d36SAndroid Build Coastguard Worker 	HKEY			key;
515*48a54d36SAndroid Build Coastguard Worker 
516*48a54d36SAndroid Build Coastguard Worker 	key = NULL;
517*48a54d36SAndroid Build Coastguard Worker 
518*48a54d36SAndroid Build Coastguard Worker 	//
519*48a54d36SAndroid Build Coastguard Worker 	// Add/Open Parameters section under service entry in registry
520*48a54d36SAndroid Build Coastguard Worker 	//
521*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
522*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
523*48a54d36SAndroid Build Coastguard Worker 
524*48a54d36SAndroid Build Coastguard Worker 	//
525*48a54d36SAndroid Build Coastguard Worker 	// If the value isn't already there, then we create it
526*48a54d36SAndroid Build Coastguard Worker 	//
527*48a54d36SAndroid Build Coastguard Worker 	err = RegQueryValueEx(key, kServiceManageLLRouting, 0, &type, (LPBYTE) &value, &valueLen);
528*48a54d36SAndroid Build Coastguard Worker 
529*48a54d36SAndroid Build Coastguard Worker 	if (err != ERROR_SUCCESS)
530*48a54d36SAndroid Build Coastguard Worker 	{
531*48a54d36SAndroid Build Coastguard Worker 		value = 1;
532*48a54d36SAndroid Build Coastguard Worker 
533*48a54d36SAndroid Build Coastguard Worker 		err = RegSetValueEx( key, kServiceManageLLRouting, 0, REG_DWORD, (const LPBYTE) &value, sizeof(DWORD) );
534*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
535*48a54d36SAndroid Build Coastguard Worker 	}
536*48a54d36SAndroid Build Coastguard Worker 
537*48a54d36SAndroid Build Coastguard Worker exit:
538*48a54d36SAndroid Build Coastguard Worker 
539*48a54d36SAndroid Build Coastguard Worker 	if ( key )
540*48a54d36SAndroid Build Coastguard Worker 	{
541*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( key );
542*48a54d36SAndroid Build Coastguard Worker 	}
543*48a54d36SAndroid Build Coastguard Worker 
544*48a54d36SAndroid Build Coastguard Worker 	return( err );
545*48a54d36SAndroid Build Coastguard Worker }
546*48a54d36SAndroid Build Coastguard Worker 
547*48a54d36SAndroid Build Coastguard Worker 
548*48a54d36SAndroid Build Coastguard Worker 
549*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
550*48a54d36SAndroid Build Coastguard Worker //	GetServiceParameters
551*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
552*48a54d36SAndroid Build Coastguard Worker 
GetServiceParameters()553*48a54d36SAndroid Build Coastguard Worker static OSStatus GetServiceParameters()
554*48a54d36SAndroid Build Coastguard Worker {
555*48a54d36SAndroid Build Coastguard Worker 	DWORD 			value;
556*48a54d36SAndroid Build Coastguard Worker 	DWORD			valueLen;
557*48a54d36SAndroid Build Coastguard Worker 	DWORD			type;
558*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
559*48a54d36SAndroid Build Coastguard Worker 	HKEY			key;
560*48a54d36SAndroid Build Coastguard Worker 
561*48a54d36SAndroid Build Coastguard Worker 	key = NULL;
562*48a54d36SAndroid Build Coastguard Worker 
563*48a54d36SAndroid Build Coastguard Worker 	//
564*48a54d36SAndroid Build Coastguard Worker 	// Add/Open Parameters section under service entry in registry
565*48a54d36SAndroid Build Coastguard Worker 	//
566*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
567*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
568*48a54d36SAndroid Build Coastguard Worker 
569*48a54d36SAndroid Build Coastguard Worker 	valueLen = sizeof(DWORD);
570*48a54d36SAndroid Build Coastguard Worker 	err = RegQueryValueEx(key, kServiceManageLLRouting, 0, &type, (LPBYTE) &value, &valueLen);
571*48a54d36SAndroid Build Coastguard Worker 	if (err == ERROR_SUCCESS)
572*48a54d36SAndroid Build Coastguard Worker 	{
573*48a54d36SAndroid Build Coastguard Worker 		gServiceManageLLRouting = (value) ? true : false;
574*48a54d36SAndroid Build Coastguard Worker 	}
575*48a54d36SAndroid Build Coastguard Worker 
576*48a54d36SAndroid Build Coastguard Worker 	valueLen = sizeof(DWORD);
577*48a54d36SAndroid Build Coastguard Worker 	err = RegQueryValueEx(key, kServiceCacheEntryCount, 0, &type, (LPBYTE) &value, &valueLen);
578*48a54d36SAndroid Build Coastguard Worker 	if (err == ERROR_SUCCESS)
579*48a54d36SAndroid Build Coastguard Worker 	{
580*48a54d36SAndroid Build Coastguard Worker 		gServiceCacheEntryCount = value;
581*48a54d36SAndroid Build Coastguard Worker 	}
582*48a54d36SAndroid Build Coastguard Worker 
583*48a54d36SAndroid Build Coastguard Worker exit:
584*48a54d36SAndroid Build Coastguard Worker 
585*48a54d36SAndroid Build Coastguard Worker 	if ( key )
586*48a54d36SAndroid Build Coastguard Worker 	{
587*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( key );
588*48a54d36SAndroid Build Coastguard Worker 	}
589*48a54d36SAndroid Build Coastguard Worker 
590*48a54d36SAndroid Build Coastguard Worker 	return( err );
591*48a54d36SAndroid Build Coastguard Worker }
592*48a54d36SAndroid Build Coastguard Worker 
593*48a54d36SAndroid Build Coastguard Worker 
594*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
595*48a54d36SAndroid Build Coastguard Worker //	CheckFirewall
596*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
597*48a54d36SAndroid Build Coastguard Worker 
CheckFirewall()598*48a54d36SAndroid Build Coastguard Worker static OSStatus CheckFirewall()
599*48a54d36SAndroid Build Coastguard Worker {
600*48a54d36SAndroid Build Coastguard Worker 	DWORD 					value;
601*48a54d36SAndroid Build Coastguard Worker 	DWORD					valueLen;
602*48a54d36SAndroid Build Coastguard Worker 	DWORD					type;
603*48a54d36SAndroid Build Coastguard Worker 	ENUM_SERVICE_STATUS	*	lpService = NULL;
604*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE				sc = NULL;
605*48a54d36SAndroid Build Coastguard Worker 	HKEY					key = NULL;
606*48a54d36SAndroid Build Coastguard Worker 	BOOL					ok;
607*48a54d36SAndroid Build Coastguard Worker 	DWORD					bytesNeeded = 0;
608*48a54d36SAndroid Build Coastguard Worker 	DWORD					srvCount;
609*48a54d36SAndroid Build Coastguard Worker 	DWORD					resumeHandle = 0;
610*48a54d36SAndroid Build Coastguard Worker 	DWORD					srvType;
611*48a54d36SAndroid Build Coastguard Worker 	DWORD					srvState;
612*48a54d36SAndroid Build Coastguard Worker 	DWORD					dwBytes = 0;
613*48a54d36SAndroid Build Coastguard Worker 	DWORD					i;
614*48a54d36SAndroid Build Coastguard Worker 	BOOL					isRunning = FALSE;
615*48a54d36SAndroid Build Coastguard Worker 	OSStatus				err = kUnknownErr;
616*48a54d36SAndroid Build Coastguard Worker 
617*48a54d36SAndroid Build Coastguard Worker 	// Check to see if the firewall service is running.  If it isn't, then
618*48a54d36SAndroid Build Coastguard Worker 	// we want to return immediately
619*48a54d36SAndroid Build Coastguard Worker 
620*48a54d36SAndroid Build Coastguard Worker 	sc = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
621*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( sc, GetLastError(), kUnknownErr );
622*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
623*48a54d36SAndroid Build Coastguard Worker 
624*48a54d36SAndroid Build Coastguard Worker 	srvType		=	SERVICE_WIN32;
625*48a54d36SAndroid Build Coastguard Worker 	srvState	=	SERVICE_STATE_ALL;
626*48a54d36SAndroid Build Coastguard Worker 
627*48a54d36SAndroid Build Coastguard Worker 	for ( ;; )
628*48a54d36SAndroid Build Coastguard Worker 	{
629*48a54d36SAndroid Build Coastguard Worker 		// Call EnumServicesStatus using the handle returned by OpenSCManager
630*48a54d36SAndroid Build Coastguard Worker 
631*48a54d36SAndroid Build Coastguard Worker 		ok = EnumServicesStatus ( sc, srvType, srvState, lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle );
632*48a54d36SAndroid Build Coastguard Worker 
633*48a54d36SAndroid Build Coastguard Worker 		if ( ok || ( GetLastError() != ERROR_MORE_DATA ) )
634*48a54d36SAndroid Build Coastguard Worker 		{
635*48a54d36SAndroid Build Coastguard Worker 			break;
636*48a54d36SAndroid Build Coastguard Worker 		}
637*48a54d36SAndroid Build Coastguard Worker 
638*48a54d36SAndroid Build Coastguard Worker 		if ( lpService )
639*48a54d36SAndroid Build Coastguard Worker 		{
640*48a54d36SAndroid Build Coastguard Worker 			free( lpService );
641*48a54d36SAndroid Build Coastguard Worker 		}
642*48a54d36SAndroid Build Coastguard Worker 
643*48a54d36SAndroid Build Coastguard Worker 		dwBytes = bytesNeeded;
644*48a54d36SAndroid Build Coastguard Worker 
645*48a54d36SAndroid Build Coastguard Worker 		lpService = ( ENUM_SERVICE_STATUS* ) malloc( dwBytes );
646*48a54d36SAndroid Build Coastguard Worker 		require_action( lpService, exit, err = mStatus_NoMemoryErr );
647*48a54d36SAndroid Build Coastguard Worker 	}
648*48a54d36SAndroid Build Coastguard Worker 
649*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, GetLastError(), kUnknownErr );
650*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
651*48a54d36SAndroid Build Coastguard Worker 
652*48a54d36SAndroid Build Coastguard Worker 	for ( i = 0; i < srvCount; i++ )
653*48a54d36SAndroid Build Coastguard Worker 	{
654*48a54d36SAndroid Build Coastguard Worker 		if ( wcscmp( lpService[i].lpServiceName, L"SharedAccess" ) == 0 )
655*48a54d36SAndroid Build Coastguard Worker 		{
656*48a54d36SAndroid Build Coastguard Worker 			if ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_RUNNING )
657*48a54d36SAndroid Build Coastguard Worker 			{
658*48a54d36SAndroid Build Coastguard Worker 				isRunning = TRUE;
659*48a54d36SAndroid Build Coastguard Worker 			}
660*48a54d36SAndroid Build Coastguard Worker 
661*48a54d36SAndroid Build Coastguard Worker 			break;
662*48a54d36SAndroid Build Coastguard Worker 		}
663*48a54d36SAndroid Build Coastguard Worker 	}
664*48a54d36SAndroid Build Coastguard Worker 
665*48a54d36SAndroid Build Coastguard Worker 	require_action( isRunning, exit, err = kUnknownErr );
666*48a54d36SAndroid Build Coastguard Worker 
667*48a54d36SAndroid Build Coastguard Worker 	// Check to see if we've managed the firewall.
668*48a54d36SAndroid Build Coastguard Worker 	// This package might have been installed, then
669*48a54d36SAndroid Build Coastguard Worker 	// the OS was upgraded to SP2 or above.  If that's
670*48a54d36SAndroid Build Coastguard Worker 	// the case, then we need to manipulate the firewall
671*48a54d36SAndroid Build Coastguard Worker 	// so networking works correctly.
672*48a54d36SAndroid Build Coastguard Worker 
673*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode, &key );
674*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
675*48a54d36SAndroid Build Coastguard Worker 
676*48a54d36SAndroid Build Coastguard Worker 	valueLen = sizeof(DWORD);
677*48a54d36SAndroid Build Coastguard Worker 	err = RegQueryValueEx(key, kServiceManageFirewall, 0, &type, (LPBYTE) &value, &valueLen);
678*48a54d36SAndroid Build Coastguard Worker 
679*48a54d36SAndroid Build Coastguard Worker 	if ((err != ERROR_SUCCESS) || (value == 0))
680*48a54d36SAndroid Build Coastguard Worker 	{
681*48a54d36SAndroid Build Coastguard Worker 		wchar_t	fullPath[ MAX_PATH ];
682*48a54d36SAndroid Build Coastguard Worker 		DWORD	size;
683*48a54d36SAndroid Build Coastguard Worker 
684*48a54d36SAndroid Build Coastguard Worker 		// Get a full path to the executable
685*48a54d36SAndroid Build Coastguard Worker 
686*48a54d36SAndroid Build Coastguard Worker 		size = GetModuleFileNameW( NULL, fullPath, MAX_PATH );
687*48a54d36SAndroid Build Coastguard Worker 		err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
688*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
689*48a54d36SAndroid Build Coastguard Worker 
690*48a54d36SAndroid Build Coastguard Worker 		err = mDNSAddToFirewall(fullPath, kServiceFirewallName);
691*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
692*48a54d36SAndroid Build Coastguard Worker 
693*48a54d36SAndroid Build Coastguard Worker 		value = 1;
694*48a54d36SAndroid Build Coastguard Worker 		err = RegSetValueEx( key, kServiceManageFirewall, 0, REG_DWORD, (const LPBYTE) &value, sizeof( DWORD ) );
695*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
696*48a54d36SAndroid Build Coastguard Worker 	}
697*48a54d36SAndroid Build Coastguard Worker 
698*48a54d36SAndroid Build Coastguard Worker exit:
699*48a54d36SAndroid Build Coastguard Worker 
700*48a54d36SAndroid Build Coastguard Worker 	if ( key )
701*48a54d36SAndroid Build Coastguard Worker 	{
702*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( key );
703*48a54d36SAndroid Build Coastguard Worker 	}
704*48a54d36SAndroid Build Coastguard Worker 
705*48a54d36SAndroid Build Coastguard Worker 	if ( lpService )
706*48a54d36SAndroid Build Coastguard Worker 	{
707*48a54d36SAndroid Build Coastguard Worker 		free( lpService );
708*48a54d36SAndroid Build Coastguard Worker 	}
709*48a54d36SAndroid Build Coastguard Worker 
710*48a54d36SAndroid Build Coastguard Worker 	if ( sc )
711*48a54d36SAndroid Build Coastguard Worker 	{
712*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle ( sc );
713*48a54d36SAndroid Build Coastguard Worker 	}
714*48a54d36SAndroid Build Coastguard Worker 
715*48a54d36SAndroid Build Coastguard Worker 	return( err );
716*48a54d36SAndroid Build Coastguard Worker }
717*48a54d36SAndroid Build Coastguard Worker 
718*48a54d36SAndroid Build Coastguard Worker 
719*48a54d36SAndroid Build Coastguard Worker 
720*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
721*48a54d36SAndroid Build Coastguard Worker //	SetServiceInfo
722*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
723*48a54d36SAndroid Build Coastguard Worker 
SetServiceInfo(SC_HANDLE inSCM,LPCTSTR inServiceName,LPCTSTR inDescription)724*48a54d36SAndroid Build Coastguard Worker static OSStatus	SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription )
725*48a54d36SAndroid Build Coastguard Worker {
726*48a54d36SAndroid Build Coastguard Worker 	OSStatus				err;
727*48a54d36SAndroid Build Coastguard Worker 	SC_LOCK					lock;
728*48a54d36SAndroid Build Coastguard Worker 	SC_HANDLE				service;
729*48a54d36SAndroid Build Coastguard Worker 	SERVICE_DESCRIPTION		description;
730*48a54d36SAndroid Build Coastguard Worker 	SERVICE_FAILURE_ACTIONS	actions;
731*48a54d36SAndroid Build Coastguard Worker 	SC_ACTION				action;
732*48a54d36SAndroid Build Coastguard Worker 	BOOL					ok;
733*48a54d36SAndroid Build Coastguard Worker 
734*48a54d36SAndroid Build Coastguard Worker 	check( inServiceName );
735*48a54d36SAndroid Build Coastguard Worker 	check( inDescription );
736*48a54d36SAndroid Build Coastguard Worker 
737*48a54d36SAndroid Build Coastguard Worker 	lock 	= NULL;
738*48a54d36SAndroid Build Coastguard Worker 	service	= NULL;
739*48a54d36SAndroid Build Coastguard Worker 
740*48a54d36SAndroid Build Coastguard Worker 	// Open the database (if not provided) and lock it to prevent other access while re-configuring.
741*48a54d36SAndroid Build Coastguard Worker 
742*48a54d36SAndroid Build Coastguard Worker 	if( !inSCM )
743*48a54d36SAndroid Build Coastguard Worker 	{
744*48a54d36SAndroid Build Coastguard Worker 		inSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
745*48a54d36SAndroid Build Coastguard Worker 		err = translate_errno( inSCM, (OSStatus) GetLastError(), kOpenErr );
746*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
747*48a54d36SAndroid Build Coastguard Worker 	}
748*48a54d36SAndroid Build Coastguard Worker 
749*48a54d36SAndroid Build Coastguard Worker 	lock = LockServiceDatabase( inSCM );
750*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( lock, (OSStatus) GetLastError(), kInUseErr );
751*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
752*48a54d36SAndroid Build Coastguard Worker 
753*48a54d36SAndroid Build Coastguard Worker 	// Open a handle to the service.
754*48a54d36SAndroid Build Coastguard Worker 
755*48a54d36SAndroid Build Coastguard Worker 	service = OpenService( inSCM, inServiceName, SERVICE_CHANGE_CONFIG|SERVICE_START );
756*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr );
757*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
758*48a54d36SAndroid Build Coastguard Worker 
759*48a54d36SAndroid Build Coastguard Worker 	// Change the description.
760*48a54d36SAndroid Build Coastguard Worker 
761*48a54d36SAndroid Build Coastguard Worker 	description.lpDescription = (LPTSTR) inDescription;
762*48a54d36SAndroid Build Coastguard Worker 	ok = ChangeServiceConfig2( service, SERVICE_CONFIG_DESCRIPTION, &description );
763*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr );
764*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
765*48a54d36SAndroid Build Coastguard Worker 
766*48a54d36SAndroid Build Coastguard Worker 	actions.dwResetPeriod	=	INFINITE;
767*48a54d36SAndroid Build Coastguard Worker 	actions.lpRebootMsg		=	NULL;
768*48a54d36SAndroid Build Coastguard Worker 	actions.lpCommand		=	NULL;
769*48a54d36SAndroid Build Coastguard Worker 	actions.cActions		=	1;
770*48a54d36SAndroid Build Coastguard Worker 	actions.lpsaActions		=	&action;
771*48a54d36SAndroid Build Coastguard Worker 	action.Delay			=	500;
772*48a54d36SAndroid Build Coastguard Worker 	action.Type				=	SC_ACTION_RESTART;
773*48a54d36SAndroid Build Coastguard Worker 
774*48a54d36SAndroid Build Coastguard Worker 	ok = ChangeServiceConfig2( service, SERVICE_CONFIG_FAILURE_ACTIONS, &actions );
775*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr );
776*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
777*48a54d36SAndroid Build Coastguard Worker 
778*48a54d36SAndroid Build Coastguard Worker 	err = ERROR_SUCCESS;
779*48a54d36SAndroid Build Coastguard Worker 
780*48a54d36SAndroid Build Coastguard Worker exit:
781*48a54d36SAndroid Build Coastguard Worker 	// Close the service and release the lock.
782*48a54d36SAndroid Build Coastguard Worker 
783*48a54d36SAndroid Build Coastguard Worker 	if( service )
784*48a54d36SAndroid Build Coastguard Worker 	{
785*48a54d36SAndroid Build Coastguard Worker 		CloseServiceHandle( service );
786*48a54d36SAndroid Build Coastguard Worker 	}
787*48a54d36SAndroid Build Coastguard Worker 	if( lock )
788*48a54d36SAndroid Build Coastguard Worker 	{
789*48a54d36SAndroid Build Coastguard Worker 		UnlockServiceDatabase( lock );
790*48a54d36SAndroid Build Coastguard Worker 	}
791*48a54d36SAndroid Build Coastguard Worker 	return( err );
792*48a54d36SAndroid Build Coastguard Worker }
793*48a54d36SAndroid Build Coastguard Worker 
794*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
795*48a54d36SAndroid Build Coastguard Worker //	ReportStatus
796*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
797*48a54d36SAndroid Build Coastguard Worker 
ReportStatus(int inType,const char * inFormat,...)798*48a54d36SAndroid Build Coastguard Worker static void	ReportStatus( int inType, const char *inFormat, ... )
799*48a54d36SAndroid Build Coastguard Worker {
800*48a54d36SAndroid Build Coastguard Worker 	if( !gServiceQuietMode )
801*48a54d36SAndroid Build Coastguard Worker 	{
802*48a54d36SAndroid Build Coastguard Worker 		va_list		args;
803*48a54d36SAndroid Build Coastguard Worker 
804*48a54d36SAndroid Build Coastguard Worker 		va_start( args, inFormat );
805*48a54d36SAndroid Build Coastguard Worker 		if( gServiceEventSource )
806*48a54d36SAndroid Build Coastguard Worker 		{
807*48a54d36SAndroid Build Coastguard Worker 			char				s[ 1024 ];
808*48a54d36SAndroid Build Coastguard Worker 			BOOL				ok;
809*48a54d36SAndroid Build Coastguard Worker 			const char *		array[ 1 ];
810*48a54d36SAndroid Build Coastguard Worker 
811*48a54d36SAndroid Build Coastguard Worker 			vsprintf( s, inFormat, args );
812*48a54d36SAndroid Build Coastguard Worker 			array[ 0 ] = s;
813*48a54d36SAndroid Build Coastguard Worker 			ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, MDNSRESPONDER_LOG, NULL, 1, 0, array, NULL );
814*48a54d36SAndroid Build Coastguard Worker 			check_translated_errno( ok, GetLastError(), kUnknownErr );
815*48a54d36SAndroid Build Coastguard Worker 		}
816*48a54d36SAndroid Build Coastguard Worker 		else
817*48a54d36SAndroid Build Coastguard Worker 		{
818*48a54d36SAndroid Build Coastguard Worker 			int		n;
819*48a54d36SAndroid Build Coastguard Worker 
820*48a54d36SAndroid Build Coastguard Worker 			n = vfprintf( stderr, inFormat, args );
821*48a54d36SAndroid Build Coastguard Worker 			check( n >= 0 );
822*48a54d36SAndroid Build Coastguard Worker 		}
823*48a54d36SAndroid Build Coastguard Worker 		va_end( args );
824*48a54d36SAndroid Build Coastguard Worker 	}
825*48a54d36SAndroid Build Coastguard Worker }
826*48a54d36SAndroid Build Coastguard Worker 
827*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
828*48a54d36SAndroid Build Coastguard Worker //	RunDirect
829*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
830*48a54d36SAndroid Build Coastguard Worker 
RunDirect(int argc,LPTSTR argv[])831*48a54d36SAndroid Build Coastguard Worker int	RunDirect( int argc, LPTSTR argv[] )
832*48a54d36SAndroid Build Coastguard Worker {
833*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
834*48a54d36SAndroid Build Coastguard Worker 	BOOL			initialized;
835*48a54d36SAndroid Build Coastguard Worker    BOOL        ok;
836*48a54d36SAndroid Build Coastguard Worker 
837*48a54d36SAndroid Build Coastguard Worker 	initialized = FALSE;
838*48a54d36SAndroid Build Coastguard Worker 
839*48a54d36SAndroid Build Coastguard Worker 	// Install a Console Control Handler to handle things like control-c signals.
840*48a54d36SAndroid Build Coastguard Worker 
841*48a54d36SAndroid Build Coastguard Worker 	ok = SetConsoleCtrlHandler( ConsoleControlHandler, TRUE );
842*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
843*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
844*48a54d36SAndroid Build Coastguard Worker 
845*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSpecificInitialize( argc, argv );
846*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
847*48a54d36SAndroid Build Coastguard Worker 	initialized = TRUE;
848*48a54d36SAndroid Build Coastguard Worker 
849*48a54d36SAndroid Build Coastguard Worker 	// Run the service. This does not return until the service quits or is stopped.
850*48a54d36SAndroid Build Coastguard Worker 
851*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Running service directly\n" );
852*48a54d36SAndroid Build Coastguard Worker 
853*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSpecificRun( argc, argv );
854*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
855*48a54d36SAndroid Build Coastguard Worker 
856*48a54d36SAndroid Build Coastguard Worker 	// Clean up.
857*48a54d36SAndroid Build Coastguard Worker 
858*48a54d36SAndroid Build Coastguard Worker exit:
859*48a54d36SAndroid Build Coastguard Worker 	if( initialized )
860*48a54d36SAndroid Build Coastguard Worker 	{
861*48a54d36SAndroid Build Coastguard Worker 		ServiceSpecificFinalize( argc, argv );
862*48a54d36SAndroid Build Coastguard Worker 	}
863*48a54d36SAndroid Build Coastguard Worker 	return( err );
864*48a54d36SAndroid Build Coastguard Worker }
865*48a54d36SAndroid Build Coastguard Worker 
866*48a54d36SAndroid Build Coastguard Worker #if 0
867*48a54d36SAndroid Build Coastguard Worker #pragma mark -
868*48a54d36SAndroid Build Coastguard Worker #endif
869*48a54d36SAndroid Build Coastguard Worker 
870*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
871*48a54d36SAndroid Build Coastguard Worker //	ServiceMain
872*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
873*48a54d36SAndroid Build Coastguard Worker 
ServiceMain(DWORD argc,LPTSTR argv[])874*48a54d36SAndroid Build Coastguard Worker static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] )
875*48a54d36SAndroid Build Coastguard Worker {
876*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
877*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
878*48a54d36SAndroid Build Coastguard Worker 
879*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSetupEventLogging();
880*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
881*48a54d36SAndroid Build Coastguard Worker 
882*48a54d36SAndroid Build Coastguard Worker 	err = GetServiceParameters();
883*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
884*48a54d36SAndroid Build Coastguard Worker 
885*48a54d36SAndroid Build Coastguard Worker 	// Initialize the service status and register the service control handler with the name of the service.
886*48a54d36SAndroid Build Coastguard Worker 
887*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwServiceType 				= SERVICE_WIN32_SHARE_PROCESS;
888*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCurrentState 				= 0;
889*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwControlsAccepted 			= SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_POWEREVENT;
890*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwWin32ExitCode 				= NO_ERROR;
891*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwServiceSpecificExitCode 	= NO_ERROR;
892*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCheckPoint 				= 0;
893*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwWaitHint 					= 0;
894*48a54d36SAndroid Build Coastguard Worker 
895*48a54d36SAndroid Build Coastguard Worker 	gServiceStatusHandle = RegisterServiceCtrlHandlerEx( argv[ 0 ], ServiceControlHandler, NULL );
896*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gServiceStatusHandle, (OSStatus) GetLastError(), kInUseErr );
897*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
898*48a54d36SAndroid Build Coastguard Worker 
899*48a54d36SAndroid Build Coastguard Worker 	// Mark the service as starting.
900*48a54d36SAndroid Build Coastguard Worker 
901*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCurrentState 	= SERVICE_START_PENDING;
902*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCheckPoint	 	= 0;
903*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwWaitHint 		= 5000;	// 5 seconds
904*48a54d36SAndroid Build Coastguard Worker 	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
905*48a54d36SAndroid Build Coastguard Worker 	check_translated_errno( ok, GetLastError(), kParamErr );
906*48a54d36SAndroid Build Coastguard Worker 
907*48a54d36SAndroid Build Coastguard Worker 	// Run the service. This does not return until the service quits or is stopped.
908*48a54d36SAndroid Build Coastguard Worker 
909*48a54d36SAndroid Build Coastguard Worker 	err = ServiceRun( (int) argc, argv );
910*48a54d36SAndroid Build Coastguard Worker 	if( err != kNoErr )
911*48a54d36SAndroid Build Coastguard Worker 	{
912*48a54d36SAndroid Build Coastguard Worker 		gServiceStatus.dwWin32ExitCode				= ERROR_SERVICE_SPECIFIC_ERROR;
913*48a54d36SAndroid Build Coastguard Worker 		gServiceStatus.dwServiceSpecificExitCode 	= (DWORD) err;
914*48a54d36SAndroid Build Coastguard Worker 	}
915*48a54d36SAndroid Build Coastguard Worker 
916*48a54d36SAndroid Build Coastguard Worker 	// Service-specific work is done so mark the service as stopped.
917*48a54d36SAndroid Build Coastguard Worker 
918*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCurrentState = SERVICE_STOPPED;
919*48a54d36SAndroid Build Coastguard Worker 	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
920*48a54d36SAndroid Build Coastguard Worker 	check_translated_errno( ok, GetLastError(), kParamErr );
921*48a54d36SAndroid Build Coastguard Worker 
922*48a54d36SAndroid Build Coastguard Worker 	// Note: The service status handle should not be closed according to Microsoft documentation.
923*48a54d36SAndroid Build Coastguard Worker 
924*48a54d36SAndroid Build Coastguard Worker exit:
925*48a54d36SAndroid Build Coastguard Worker 	if( gServiceEventSource )
926*48a54d36SAndroid Build Coastguard Worker 	{
927*48a54d36SAndroid Build Coastguard Worker 		ok = DeregisterEventSource( gServiceEventSource );
928*48a54d36SAndroid Build Coastguard Worker 		check_translated_errno( ok, GetLastError(), kUnknownErr );
929*48a54d36SAndroid Build Coastguard Worker 		gServiceEventSource = NULL;
930*48a54d36SAndroid Build Coastguard Worker 	}
931*48a54d36SAndroid Build Coastguard Worker }
932*48a54d36SAndroid Build Coastguard Worker 
933*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
934*48a54d36SAndroid Build Coastguard Worker //	ServiceSetupEventLogging
935*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
936*48a54d36SAndroid Build Coastguard Worker 
ServiceSetupEventLogging(void)937*48a54d36SAndroid Build Coastguard Worker static OSStatus	ServiceSetupEventLogging( void )
938*48a54d36SAndroid Build Coastguard Worker {
939*48a54d36SAndroid Build Coastguard Worker 	OSStatus			err;
940*48a54d36SAndroid Build Coastguard Worker 	HKEY				key;
941*48a54d36SAndroid Build Coastguard Worker 	LPCTSTR				s;
942*48a54d36SAndroid Build Coastguard Worker 	DWORD				typesSupported;
943*48a54d36SAndroid Build Coastguard Worker 	TCHAR				path[ MAX_PATH ];
944*48a54d36SAndroid Build Coastguard Worker 	DWORD 				n;
945*48a54d36SAndroid Build Coastguard Worker 
946*48a54d36SAndroid Build Coastguard Worker 	key = NULL;
947*48a54d36SAndroid Build Coastguard Worker 
948*48a54d36SAndroid Build Coastguard Worker 	// Add/Open source name as a sub-key under the Application key in the EventLog registry key.
949*48a54d36SAndroid Build Coastguard Worker 
950*48a54d36SAndroid Build Coastguard Worker 	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") kServiceName;
951*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
952*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
953*48a54d36SAndroid Build Coastguard Worker 
954*48a54d36SAndroid Build Coastguard Worker 	// Add the name to the EventMessageFile subkey.
955*48a54d36SAndroid Build Coastguard Worker 
956*48a54d36SAndroid Build Coastguard Worker 	path[ 0 ] = '\0';
957*48a54d36SAndroid Build Coastguard Worker 	GetModuleFileName( NULL, path, MAX_PATH );
958*48a54d36SAndroid Build Coastguard Worker 	n = (DWORD) ( ( StrLen( path ) + 1 ) * sizeof( TCHAR ) );
959*48a54d36SAndroid Build Coastguard Worker 	err = RegSetValueEx( key, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (const LPBYTE) path, n );
960*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
961*48a54d36SAndroid Build Coastguard Worker 
962*48a54d36SAndroid Build Coastguard Worker 	// Set the supported event types in the TypesSupported subkey.
963*48a54d36SAndroid Build Coastguard Worker 
964*48a54d36SAndroid Build Coastguard Worker 	typesSupported = 0
965*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_SUCCESS
966*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_ERROR_TYPE
967*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_WARNING_TYPE
968*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_INFORMATION_TYPE
969*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_AUDIT_SUCCESS
970*48a54d36SAndroid Build Coastguard Worker 					 | EVENTLOG_AUDIT_FAILURE;
971*48a54d36SAndroid Build Coastguard Worker 	err = RegSetValueEx( key, TEXT("TypesSupported"), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) );
972*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
973*48a54d36SAndroid Build Coastguard Worker 
974*48a54d36SAndroid Build Coastguard Worker 	// Set up the event source.
975*48a54d36SAndroid Build Coastguard Worker 
976*48a54d36SAndroid Build Coastguard Worker 	gServiceEventSource = RegisterEventSource( NULL, kServiceName );
977*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gServiceEventSource, (OSStatus) GetLastError(), kParamErr );
978*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
979*48a54d36SAndroid Build Coastguard Worker 
980*48a54d36SAndroid Build Coastguard Worker exit:
981*48a54d36SAndroid Build Coastguard Worker 	if( key )
982*48a54d36SAndroid Build Coastguard Worker 	{
983*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( key );
984*48a54d36SAndroid Build Coastguard Worker 	}
985*48a54d36SAndroid Build Coastguard Worker 	return( err );
986*48a54d36SAndroid Build Coastguard Worker }
987*48a54d36SAndroid Build Coastguard Worker 
988*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
989*48a54d36SAndroid Build Coastguard Worker //	HandlePowerSuspend
990*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
991*48a54d36SAndroid Build Coastguard Worker 
HandlePowerSuspend(void * v)992*48a54d36SAndroid Build Coastguard Worker static void HandlePowerSuspend( void * v )
993*48a54d36SAndroid Build Coastguard Worker {
994*48a54d36SAndroid Build Coastguard Worker 	LARGE_INTEGER	timeout;
995*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
996*48a54d36SAndroid Build Coastguard Worker 
997*48a54d36SAndroid Build Coastguard Worker 	( void ) v;
998*48a54d36SAndroid Build Coastguard Worker 
999*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelInfo, DEBUG_NAME "HandlePowerSuspend\n" );
1000*48a54d36SAndroid Build Coastguard Worker 
1001*48a54d36SAndroid Build Coastguard Worker 	gMDNSRecord.SystemWakeOnLANEnabled = SystemWakeForNetworkAccess( &timeout );
1002*48a54d36SAndroid Build Coastguard Worker 
1003*48a54d36SAndroid Build Coastguard Worker 	if ( gMDNSRecord.SystemWakeOnLANEnabled )
1004*48a54d36SAndroid Build Coastguard Worker 	{
1005*48a54d36SAndroid Build Coastguard Worker 		ok = SetWaitableTimer( gSPSWakeupEvent, &timeout, 0, NULL, NULL, TRUE );
1006*48a54d36SAndroid Build Coastguard Worker 		check( ok );
1007*48a54d36SAndroid Build Coastguard Worker 	}
1008*48a54d36SAndroid Build Coastguard Worker 
1009*48a54d36SAndroid Build Coastguard Worker 	mDNSCoreMachineSleep(&gMDNSRecord, TRUE);
1010*48a54d36SAndroid Build Coastguard Worker }
1011*48a54d36SAndroid Build Coastguard Worker 
1012*48a54d36SAndroid Build Coastguard Worker 
1013*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1014*48a54d36SAndroid Build Coastguard Worker //	HandlePowerResumeSuspend
1015*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1016*48a54d36SAndroid Build Coastguard Worker 
HandlePowerResumeSuspend(void * v)1017*48a54d36SAndroid Build Coastguard Worker static void HandlePowerResumeSuspend( void * v )
1018*48a54d36SAndroid Build Coastguard Worker {
1019*48a54d36SAndroid Build Coastguard Worker 	( void ) v;
1020*48a54d36SAndroid Build Coastguard Worker 
1021*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelInfo, DEBUG_NAME "HandlePowerResumeSuspend\n" );
1022*48a54d36SAndroid Build Coastguard Worker 
1023*48a54d36SAndroid Build Coastguard Worker 	if ( gSPSWakeupEvent )
1024*48a54d36SAndroid Build Coastguard Worker 	{
1025*48a54d36SAndroid Build Coastguard Worker 		CancelWaitableTimer( gSPSWakeupEvent );
1026*48a54d36SAndroid Build Coastguard Worker 	}
1027*48a54d36SAndroid Build Coastguard Worker 
1028*48a54d36SAndroid Build Coastguard Worker 	if ( gSPSSleepEvent )
1029*48a54d36SAndroid Build Coastguard Worker 	{
1030*48a54d36SAndroid Build Coastguard Worker 		CancelWaitableTimer( gSPSSleepEvent );
1031*48a54d36SAndroid Build Coastguard Worker 	}
1032*48a54d36SAndroid Build Coastguard Worker 
1033*48a54d36SAndroid Build Coastguard Worker 	mDNSCoreMachineSleep(&gMDNSRecord, FALSE);
1034*48a54d36SAndroid Build Coastguard Worker }
1035*48a54d36SAndroid Build Coastguard Worker 
1036*48a54d36SAndroid Build Coastguard Worker 
1037*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1038*48a54d36SAndroid Build Coastguard Worker //	ServiceControlHandler
1039*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1040*48a54d36SAndroid Build Coastguard Worker 
ServiceControlHandler(DWORD inControl,DWORD inEventType,LPVOID inEventData,LPVOID inContext)1041*48a54d36SAndroid Build Coastguard Worker static DWORD WINAPI	ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext )
1042*48a54d36SAndroid Build Coastguard Worker {
1043*48a54d36SAndroid Build Coastguard Worker 	BOOL		setStatus;
1044*48a54d36SAndroid Build Coastguard Worker 	BOOL		ok;
1045*48a54d36SAndroid Build Coastguard Worker 
1046*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( inEventData );
1047*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( inContext );
1048*48a54d36SAndroid Build Coastguard Worker 
1049*48a54d36SAndroid Build Coastguard Worker 	setStatus = TRUE;
1050*48a54d36SAndroid Build Coastguard Worker 	switch( inControl )
1051*48a54d36SAndroid Build Coastguard Worker 	{
1052*48a54d36SAndroid Build Coastguard Worker 		case SERVICE_CONTROL_STOP:
1053*48a54d36SAndroid Build Coastguard Worker 		case SERVICE_CONTROL_SHUTDOWN:
1054*48a54d36SAndroid Build Coastguard Worker 			dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: SERVICE_CONTROL_STOP|SERVICE_CONTROL_SHUTDOWN\n" );
1055*48a54d36SAndroid Build Coastguard Worker 
1056*48a54d36SAndroid Build Coastguard Worker 			ServiceStop();
1057*48a54d36SAndroid Build Coastguard Worker 			setStatus = FALSE;
1058*48a54d36SAndroid Build Coastguard Worker 			break;
1059*48a54d36SAndroid Build Coastguard Worker 
1060*48a54d36SAndroid Build Coastguard Worker 		case SERVICE_CONTROL_POWEREVENT:
1061*48a54d36SAndroid Build Coastguard Worker 
1062*48a54d36SAndroid Build Coastguard Worker 			if (inEventType == PBT_APMSUSPEND)
1063*48a54d36SAndroid Build Coastguard Worker 			{
1064*48a54d36SAndroid Build Coastguard Worker 				dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMSUSPEND\n" );
1065*48a54d36SAndroid Build Coastguard Worker 
1066*48a54d36SAndroid Build Coastguard Worker 				QueueUserAPC( ( PAPCFUNC ) HandlePowerSuspend, gMDNSRecord.p->mainThread, ( ULONG_PTR ) NULL );
1067*48a54d36SAndroid Build Coastguard Worker 			}
1068*48a54d36SAndroid Build Coastguard Worker 			else if (inEventType == PBT_APMRESUMESUSPEND)
1069*48a54d36SAndroid Build Coastguard Worker 			{
1070*48a54d36SAndroid Build Coastguard Worker 				dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMRESUMESUSPEND\n" );
1071*48a54d36SAndroid Build Coastguard Worker 
1072*48a54d36SAndroid Build Coastguard Worker 				QueueUserAPC( ( PAPCFUNC ) HandlePowerResumeSuspend, gMDNSRecord.p->mainThread, ( ULONG_PTR ) NULL );
1073*48a54d36SAndroid Build Coastguard Worker 			}
1074*48a54d36SAndroid Build Coastguard Worker 
1075*48a54d36SAndroid Build Coastguard Worker 			break;
1076*48a54d36SAndroid Build Coastguard Worker 
1077*48a54d36SAndroid Build Coastguard Worker 		default:
1078*48a54d36SAndroid Build Coastguard Worker 			dlog( kDebugLevelNotice, DEBUG_NAME "ServiceControlHandler: event (0x%08X)\n", inControl );
1079*48a54d36SAndroid Build Coastguard Worker 			break;
1080*48a54d36SAndroid Build Coastguard Worker 	}
1081*48a54d36SAndroid Build Coastguard Worker 
1082*48a54d36SAndroid Build Coastguard Worker 	if( setStatus && gServiceStatusHandle )
1083*48a54d36SAndroid Build Coastguard Worker 	{
1084*48a54d36SAndroid Build Coastguard Worker 		ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
1085*48a54d36SAndroid Build Coastguard Worker 		check_translated_errno( ok, GetLastError(), kUnknownErr );
1086*48a54d36SAndroid Build Coastguard Worker 	}
1087*48a54d36SAndroid Build Coastguard Worker 
1088*48a54d36SAndroid Build Coastguard Worker 	return NO_ERROR;
1089*48a54d36SAndroid Build Coastguard Worker }
1090*48a54d36SAndroid Build Coastguard Worker 
1091*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1092*48a54d36SAndroid Build Coastguard Worker //	ServiceRun
1093*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1094*48a54d36SAndroid Build Coastguard Worker 
ServiceRun(int argc,LPTSTR argv[])1095*48a54d36SAndroid Build Coastguard Worker static OSStatus	ServiceRun( int argc, LPTSTR argv[] )
1096*48a54d36SAndroid Build Coastguard Worker {
1097*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
1098*48a54d36SAndroid Build Coastguard Worker 	BOOL			initialized;
1099*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
1100*48a54d36SAndroid Build Coastguard Worker 
1101*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argc );
1102*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argv );
1103*48a54d36SAndroid Build Coastguard Worker 
1104*48a54d36SAndroid Build Coastguard Worker 	initialized = FALSE;
1105*48a54d36SAndroid Build Coastguard Worker 
1106*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/5727548> Make the service as running before we call ServiceSpecificInitialize. We've
1107*48a54d36SAndroid Build Coastguard Worker 	// had reports that some machines with McAfee firewall installed cause a problem with iTunes installation.
1108*48a54d36SAndroid Build Coastguard Worker 	// We think that the firewall product is interferring with code in ServiceSpecificInitialize. So as a
1109*48a54d36SAndroid Build Coastguard Worker 	// simple workaround, we'll mark us as running *before* we call ServiceSpecificInitialize. This will unblock
1110*48a54d36SAndroid Build Coastguard Worker 	// any installers that are waiting for our state to change.
1111*48a54d36SAndroid Build Coastguard Worker 
1112*48a54d36SAndroid Build Coastguard Worker 	gServiceStatus.dwCurrentState = SERVICE_RUNNING;
1113*48a54d36SAndroid Build Coastguard Worker 	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
1114*48a54d36SAndroid Build Coastguard Worker 	check_translated_errno( ok, GetLastError(), kParamErr );
1115*48a54d36SAndroid Build Coastguard Worker 
1116*48a54d36SAndroid Build Coastguard Worker 	// Initialize the service-specific stuff
1117*48a54d36SAndroid Build Coastguard Worker 
1118*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSpecificInitialize( argc, argv );
1119*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1120*48a54d36SAndroid Build Coastguard Worker 	initialized = TRUE;
1121*48a54d36SAndroid Build Coastguard Worker 
1122*48a54d36SAndroid Build Coastguard Worker 	err = CheckFirewall();
1123*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
1124*48a54d36SAndroid Build Coastguard Worker 
1125*48a54d36SAndroid Build Coastguard Worker 	if ( err )
1126*48a54d36SAndroid Build Coastguard Worker 	{
1127*48a54d36SAndroid Build Coastguard Worker 		gRetryFirewall = TRUE;
1128*48a54d36SAndroid Build Coastguard Worker 	}
1129*48a54d36SAndroid Build Coastguard Worker 
1130*48a54d36SAndroid Build Coastguard Worker 	// Run the service-specific stuff. This does not return until the service quits or is stopped.
1131*48a54d36SAndroid Build Coastguard Worker 
1132*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service started\n" );
1133*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSpecificRun( argc, argv );
1134*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service stopped (%d)\n", err );
1135*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1136*48a54d36SAndroid Build Coastguard Worker 
1137*48a54d36SAndroid Build Coastguard Worker 	// Service stopped. Clean up and we're done.
1138*48a54d36SAndroid Build Coastguard Worker 
1139*48a54d36SAndroid Build Coastguard Worker exit:
1140*48a54d36SAndroid Build Coastguard Worker 	if( initialized )
1141*48a54d36SAndroid Build Coastguard Worker 	{
1142*48a54d36SAndroid Build Coastguard Worker 		ServiceSpecificFinalize( argc, argv );
1143*48a54d36SAndroid Build Coastguard Worker 	}
1144*48a54d36SAndroid Build Coastguard Worker 	return( err );
1145*48a54d36SAndroid Build Coastguard Worker }
1146*48a54d36SAndroid Build Coastguard Worker 
1147*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1148*48a54d36SAndroid Build Coastguard Worker //	ServiceStop
1149*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1150*48a54d36SAndroid Build Coastguard Worker 
ServiceStop(void)1151*48a54d36SAndroid Build Coastguard Worker static void	ServiceStop( void )
1152*48a54d36SAndroid Build Coastguard Worker {
1153*48a54d36SAndroid Build Coastguard Worker 	BOOL			ok;
1154*48a54d36SAndroid Build Coastguard Worker 	OSStatus		err;
1155*48a54d36SAndroid Build Coastguard Worker 
1156*48a54d36SAndroid Build Coastguard Worker 	// Signal the event to cause the service to exit.
1157*48a54d36SAndroid Build Coastguard Worker 
1158*48a54d36SAndroid Build Coastguard Worker 	if( gServiceStatusHandle )
1159*48a54d36SAndroid Build Coastguard Worker 	{
1160*48a54d36SAndroid Build Coastguard Worker 		gServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
1161*48a54d36SAndroid Build Coastguard Worker 		ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
1162*48a54d36SAndroid Build Coastguard Worker 		check_translated_errno( ok, GetLastError(), kParamErr );
1163*48a54d36SAndroid Build Coastguard Worker 	}
1164*48a54d36SAndroid Build Coastguard Worker 
1165*48a54d36SAndroid Build Coastguard Worker 	err = ServiceSpecificStop();
1166*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
1167*48a54d36SAndroid Build Coastguard Worker }
1168*48a54d36SAndroid Build Coastguard Worker 
1169*48a54d36SAndroid Build Coastguard Worker #if 0
1170*48a54d36SAndroid Build Coastguard Worker #pragma mark -
1171*48a54d36SAndroid Build Coastguard Worker #pragma mark == Service Specific ==
1172*48a54d36SAndroid Build Coastguard Worker #endif
1173*48a54d36SAndroid Build Coastguard Worker 
1174*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1175*48a54d36SAndroid Build Coastguard Worker //	ServiceSpecificInitialize
1176*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1177*48a54d36SAndroid Build Coastguard Worker 
ServiceSpecificInitialize(int argc,LPTSTR argv[])1178*48a54d36SAndroid Build Coastguard Worker static OSStatus	ServiceSpecificInitialize( int argc, LPTSTR argv[] )
1179*48a54d36SAndroid Build Coastguard Worker {
1180*48a54d36SAndroid Build Coastguard Worker 	OSVERSIONINFO osInfo;
1181*48a54d36SAndroid Build Coastguard Worker 	OSStatus err;
1182*48a54d36SAndroid Build Coastguard Worker 	BOOL ok;
1183*48a54d36SAndroid Build Coastguard Worker 
1184*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argc );
1185*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argv );
1186*48a54d36SAndroid Build Coastguard Worker 
1187*48a54d36SAndroid Build Coastguard Worker 	mDNSPlatformMemZero( &gMDNSRecord, sizeof gMDNSRecord);
1188*48a54d36SAndroid Build Coastguard Worker 	mDNSPlatformMemZero( &gPlatformStorage, sizeof gPlatformStorage);
1189*48a54d36SAndroid Build Coastguard Worker 
1190*48a54d36SAndroid Build Coastguard Worker 	gPlatformStorage.registerWaitableEventFunc = RegisterWaitableEvent;
1191*48a54d36SAndroid Build Coastguard Worker 	gPlatformStorage.unregisterWaitableEventFunc = UnregisterWaitableEvent;
1192*48a54d36SAndroid Build Coastguard Worker 	gPlatformStorage.reportStatusFunc = ReportStatus;
1193*48a54d36SAndroid Build Coastguard Worker 
1194*48a54d36SAndroid Build Coastguard Worker 	err = mDNS_Init( &gMDNSRecord, &gPlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, CoreCallback, mDNS_Init_NoInitCallbackContext);
1195*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit);
1196*48a54d36SAndroid Build Coastguard Worker 
1197*48a54d36SAndroid Build Coastguard Worker 	err = SetupNotifications();
1198*48a54d36SAndroid Build Coastguard Worker 	check_noerr( err );
1199*48a54d36SAndroid Build Coastguard Worker 
1200*48a54d36SAndroid Build Coastguard Worker 	err = udsserver_init(mDNSNULL, 0);
1201*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit);
1202*48a54d36SAndroid Build Coastguard Worker 
1203*48a54d36SAndroid Build Coastguard Worker 	//
1204*48a54d36SAndroid Build Coastguard Worker 	// Get the version of Windows that we're running on
1205*48a54d36SAndroid Build Coastguard Worker 	//
1206*48a54d36SAndroid Build Coastguard Worker 	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
1207*48a54d36SAndroid Build Coastguard Worker 	ok = GetVersionEx( &osInfo );
1208*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
1209*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1210*48a54d36SAndroid Build Coastguard Worker 	gOSMajorVersion = osInfo.dwMajorVersion;
1211*48a54d36SAndroid Build Coastguard Worker 	gOSMinorVersion = osInfo.dwMinorVersion;
1212*48a54d36SAndroid Build Coastguard Worker 
1213*48a54d36SAndroid Build Coastguard Worker 	SetLLRoute( &gMDNSRecord );
1214*48a54d36SAndroid Build Coastguard Worker 
1215*48a54d36SAndroid Build Coastguard Worker exit:
1216*48a54d36SAndroid Build Coastguard Worker 	if( err != kNoErr )
1217*48a54d36SAndroid Build Coastguard Worker 	{
1218*48a54d36SAndroid Build Coastguard Worker 		ServiceSpecificFinalize( argc, argv );
1219*48a54d36SAndroid Build Coastguard Worker 	}
1220*48a54d36SAndroid Build Coastguard Worker 	return( err );
1221*48a54d36SAndroid Build Coastguard Worker }
1222*48a54d36SAndroid Build Coastguard Worker 
1223*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1224*48a54d36SAndroid Build Coastguard Worker //	ServiceSpecificRun
1225*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1226*48a54d36SAndroid Build Coastguard Worker 
ServiceSpecificRun(int argc,LPTSTR argv[])1227*48a54d36SAndroid Build Coastguard Worker static OSStatus	ServiceSpecificRun( int argc, LPTSTR argv[] )
1228*48a54d36SAndroid Build Coastguard Worker {
1229*48a54d36SAndroid Build Coastguard Worker 	HANDLE	*	waitList;
1230*48a54d36SAndroid Build Coastguard Worker 	int			waitListCount;
1231*48a54d36SAndroid Build Coastguard Worker 	DWORD		timeout;
1232*48a54d36SAndroid Build Coastguard Worker 	DWORD		result;
1233*48a54d36SAndroid Build Coastguard Worker 	BOOL		done;
1234*48a54d36SAndroid Build Coastguard Worker 	mStatus		err;
1235*48a54d36SAndroid Build Coastguard Worker 
1236*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argc );
1237*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argv );
1238*48a54d36SAndroid Build Coastguard Worker 
1239*48a54d36SAndroid Build Coastguard Worker 	timeout = ( gRetryFirewall ) ? kRetryFirewallPeriod : INFINITE;
1240*48a54d36SAndroid Build Coastguard Worker 
1241*48a54d36SAndroid Build Coastguard Worker 	err = SetupInterfaceList( &gMDNSRecord );
1242*48a54d36SAndroid Build Coastguard Worker 	check( !err );
1243*48a54d36SAndroid Build Coastguard Worker 
1244*48a54d36SAndroid Build Coastguard Worker 	err = uDNS_SetupDNSConfig( &gMDNSRecord );
1245*48a54d36SAndroid Build Coastguard Worker 	check( !err );
1246*48a54d36SAndroid Build Coastguard Worker 
1247*48a54d36SAndroid Build Coastguard Worker 	done = FALSE;
1248*48a54d36SAndroid Build Coastguard Worker 
1249*48a54d36SAndroid Build Coastguard Worker 	// Main event loop.
1250*48a54d36SAndroid Build Coastguard Worker 
1251*48a54d36SAndroid Build Coastguard Worker 	while( !done )
1252*48a54d36SAndroid Build Coastguard Worker 	{
1253*48a54d36SAndroid Build Coastguard Worker 		waitList		= NULL;
1254*48a54d36SAndroid Build Coastguard Worker 		waitListCount	= 0;
1255*48a54d36SAndroid Build Coastguard Worker 
1256*48a54d36SAndroid Build Coastguard Worker 		err = SetupWaitList( &gMDNSRecord, &waitList, &waitListCount );
1257*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
1258*48a54d36SAndroid Build Coastguard Worker 
1259*48a54d36SAndroid Build Coastguard Worker 		gEventSourceListChanged = FALSE;
1260*48a54d36SAndroid Build Coastguard Worker 
1261*48a54d36SAndroid Build Coastguard Worker 		while ( !gEventSourceListChanged )
1262*48a54d36SAndroid Build Coastguard Worker 		{
1263*48a54d36SAndroid Build Coastguard Worker 			static mDNSs32 RepeatedBusy = 0;
1264*48a54d36SAndroid Build Coastguard Worker 			mDNSs32 nextTimerEvent;
1265*48a54d36SAndroid Build Coastguard Worker 
1266*48a54d36SAndroid Build Coastguard Worker 			// Give the mDNS core a chance to do its work and determine next event time.
1267*48a54d36SAndroid Build Coastguard Worker 
1268*48a54d36SAndroid Build Coastguard Worker 			nextTimerEvent = udsserver_idle( mDNS_Execute( &gMDNSRecord ) - mDNS_TimeNow( &gMDNSRecord ) );
1269*48a54d36SAndroid Build Coastguard Worker 
1270*48a54d36SAndroid Build Coastguard Worker 			if      ( nextTimerEvent < 0)					nextTimerEvent = 0;
1271*48a54d36SAndroid Build Coastguard Worker 			else if ( nextTimerEvent > (0x7FFFFFFF / 1000))	nextTimerEvent = 0x7FFFFFFF / mDNSPlatformOneSecond;
1272*48a54d36SAndroid Build Coastguard Worker 			else											nextTimerEvent = ( nextTimerEvent * 1000) / mDNSPlatformOneSecond;
1273*48a54d36SAndroid Build Coastguard Worker 
1274*48a54d36SAndroid Build Coastguard Worker 			// Debugging sanity check, to guard against CPU spins
1275*48a54d36SAndroid Build Coastguard Worker 
1276*48a54d36SAndroid Build Coastguard Worker 			if ( nextTimerEvent > 0 )
1277*48a54d36SAndroid Build Coastguard Worker 			{
1278*48a54d36SAndroid Build Coastguard Worker 				RepeatedBusy = 0;
1279*48a54d36SAndroid Build Coastguard Worker 			}
1280*48a54d36SAndroid Build Coastguard Worker 			else
1281*48a54d36SAndroid Build Coastguard Worker 			{
1282*48a54d36SAndroid Build Coastguard Worker 				nextTimerEvent = 1;
1283*48a54d36SAndroid Build Coastguard Worker 
1284*48a54d36SAndroid Build Coastguard Worker 				if ( ++RepeatedBusy >= mDNSPlatformOneSecond )
1285*48a54d36SAndroid Build Coastguard Worker 				{
1286*48a54d36SAndroid Build Coastguard Worker 					ShowTaskSchedulingError( &gMDNSRecord );
1287*48a54d36SAndroid Build Coastguard Worker 					RepeatedBusy = 0;
1288*48a54d36SAndroid Build Coastguard Worker 				}
1289*48a54d36SAndroid Build Coastguard Worker 			}
1290*48a54d36SAndroid Build Coastguard Worker 
1291*48a54d36SAndroid Build Coastguard Worker 			if ( gMDNSRecord.ShutdownTime )
1292*48a54d36SAndroid Build Coastguard Worker 			{
1293*48a54d36SAndroid Build Coastguard Worker 				mDNSs32 now = mDNS_TimeNow( &gMDNSRecord );
1294*48a54d36SAndroid Build Coastguard Worker 
1295*48a54d36SAndroid Build Coastguard Worker 				if ( mDNS_ExitNow( &gMDNSRecord, now ) )
1296*48a54d36SAndroid Build Coastguard Worker 				{
1297*48a54d36SAndroid Build Coastguard Worker 					mDNS_FinalExit( &gMDNSRecord );
1298*48a54d36SAndroid Build Coastguard Worker 					done = TRUE;
1299*48a54d36SAndroid Build Coastguard Worker 					break;
1300*48a54d36SAndroid Build Coastguard Worker 				}
1301*48a54d36SAndroid Build Coastguard Worker 
1302*48a54d36SAndroid Build Coastguard Worker 				if ( nextTimerEvent - gMDNSRecord.ShutdownTime >= 0 )
1303*48a54d36SAndroid Build Coastguard Worker 				{
1304*48a54d36SAndroid Build Coastguard Worker 					nextTimerEvent = gMDNSRecord.ShutdownTime;
1305*48a54d36SAndroid Build Coastguard Worker 				}
1306*48a54d36SAndroid Build Coastguard Worker 			}
1307*48a54d36SAndroid Build Coastguard Worker 
1308*48a54d36SAndroid Build Coastguard Worker 			// Wait until something occurs (e.g. cancel, incoming packet, or timeout).
1309*48a54d36SAndroid Build Coastguard Worker 			//
1310*48a54d36SAndroid Build Coastguard Worker 			// Note: There seems to be a bug in WinSock with respect to Alertable I/O. According
1311*48a54d36SAndroid Build Coastguard Worker 			// to MSDN <http://msdn.microsoft.com/en-us/library/aa363772(VS.85).aspx>, Alertable I/O
1312*48a54d36SAndroid Build Coastguard Worker 			// callbacks will only be invoked during the following calls (when the caller sets
1313*48a54d36SAndroid Build Coastguard Worker 			// the appropriate flag):
1314*48a54d36SAndroid Build Coastguard Worker 			//
1315*48a54d36SAndroid Build Coastguard Worker 			// - SleepEx
1316*48a54d36SAndroid Build Coastguard Worker 			// - WaitForSingleObjectEx
1317*48a54d36SAndroid Build Coastguard Worker 			// - WaitForMultipleObjectsEx
1318*48a54d36SAndroid Build Coastguard Worker 			// - SignalObjectAndWait
1319*48a54d36SAndroid Build Coastguard Worker 			// - MsgWaitForMultipleObjectsEx
1320*48a54d36SAndroid Build Coastguard Worker 			//
1321*48a54d36SAndroid Build Coastguard Worker 			// However, we have seen callbacks be invoked during calls to bind() (and maybe others). If there
1322*48a54d36SAndroid Build Coastguard Worker 			// weren't a bug, then socket events would only be queued during the call to WaitForMultipleObjects() and
1323*48a54d36SAndroid Build Coastguard Worker 			// we'd only have to check them once afterwards. However since that doesn't seem to be the case, we'll
1324*48a54d36SAndroid Build Coastguard Worker 			// check the queue both before we call WaitForMultipleObjects() and after.
1325*48a54d36SAndroid Build Coastguard Worker 
1326*48a54d36SAndroid Build Coastguard Worker 			DispatchSocketEvents( &gMDNSRecord );
1327*48a54d36SAndroid Build Coastguard Worker 			result = WaitForMultipleObjectsEx( ( DWORD ) waitListCount, waitList, FALSE, (DWORD) nextTimerEvent, TRUE );
1328*48a54d36SAndroid Build Coastguard Worker 			check( result != WAIT_FAILED );
1329*48a54d36SAndroid Build Coastguard Worker 			DispatchSocketEvents( &gMDNSRecord );
1330*48a54d36SAndroid Build Coastguard Worker 
1331*48a54d36SAndroid Build Coastguard Worker 			if ( result != WAIT_FAILED )
1332*48a54d36SAndroid Build Coastguard Worker 			{
1333*48a54d36SAndroid Build Coastguard Worker 				if ( result == WAIT_TIMEOUT )
1334*48a54d36SAndroid Build Coastguard Worker 				{
1335*48a54d36SAndroid Build Coastguard Worker 					// Next task timeout occurred. Loop back up to give mDNS core a chance to work.
1336*48a54d36SAndroid Build Coastguard Worker 
1337*48a54d36SAndroid Build Coastguard Worker 					dlog( kDebugLevelChatty - 1, DEBUG_NAME "timeout\n" );
1338*48a54d36SAndroid Build Coastguard Worker 					continue;
1339*48a54d36SAndroid Build Coastguard Worker 				}
1340*48a54d36SAndroid Build Coastguard Worker 				else if ( result == WAIT_IO_COMPLETION )
1341*48a54d36SAndroid Build Coastguard Worker 				{
1342*48a54d36SAndroid Build Coastguard Worker 					dlog( kDebugLevelChatty - 1, DEBUG_NAME "i/o completion\n" );
1343*48a54d36SAndroid Build Coastguard Worker 					continue;
1344*48a54d36SAndroid Build Coastguard Worker 				}
1345*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListStopEvent )
1346*48a54d36SAndroid Build Coastguard Worker 				{
1347*48a54d36SAndroid Build Coastguard Worker 					// Stop event. Set the done flag and break to exit.
1348*48a54d36SAndroid Build Coastguard Worker 
1349*48a54d36SAndroid Build Coastguard Worker 					dlog( kDebugLevelVerbose, DEBUG_NAME "stopping...\n" );
1350*48a54d36SAndroid Build Coastguard Worker 					udsserver_exit();
1351*48a54d36SAndroid Build Coastguard Worker 					mDNS_StartExit( &gMDNSRecord );
1352*48a54d36SAndroid Build Coastguard Worker 					break;
1353*48a54d36SAndroid Build Coastguard Worker 				}
1354*48a54d36SAndroid Build Coastguard Worker 				else if( result == kWaitListInterfaceListChangedEvent )
1355*48a54d36SAndroid Build Coastguard Worker 				{
1356*48a54d36SAndroid Build Coastguard Worker 					int		inBuffer;
1357*48a54d36SAndroid Build Coastguard Worker 					int		outBuffer;
1358*48a54d36SAndroid Build Coastguard Worker 					DWORD	outSize;
1359*48a54d36SAndroid Build Coastguard Worker 
1360*48a54d36SAndroid Build Coastguard Worker 					// It would be nice to come up with a more elegant solution to this, but it seems that
1361*48a54d36SAndroid Build Coastguard Worker 					// GetAdaptersAddresses doesn't always stay in sync after network changed events.  So as
1362*48a54d36SAndroid Build Coastguard Worker 					// as a simple workaround, we'll pause for a couple of seconds before processing the change.
1363*48a54d36SAndroid Build Coastguard Worker 
1364*48a54d36SAndroid Build Coastguard Worker 					// We arrived at 2 secs by trial and error. We could reproduce the problem after sleeping
1365*48a54d36SAndroid Build Coastguard Worker 					// for 500 msec and 750 msec, but couldn't after sleeping for 1 sec.  We added another
1366*48a54d36SAndroid Build Coastguard Worker 					// second on top of that to account for machine load or some other exigency.
1367*48a54d36SAndroid Build Coastguard Worker 
1368*48a54d36SAndroid Build Coastguard Worker 					Sleep( 2000 );
1369*48a54d36SAndroid Build Coastguard Worker 
1370*48a54d36SAndroid Build Coastguard Worker 					// Interface list changed event. Break out of the inner loop to re-setup the wait list.
1371*48a54d36SAndroid Build Coastguard Worker 
1372*48a54d36SAndroid Build Coastguard Worker 					InterfaceListDidChange( &gMDNSRecord );
1373*48a54d36SAndroid Build Coastguard Worker 
1374*48a54d36SAndroid Build Coastguard Worker 					// reset the event handler
1375*48a54d36SAndroid Build Coastguard Worker 					inBuffer	= 0;
1376*48a54d36SAndroid Build Coastguard Worker 					outBuffer	= 0;
1377*48a54d36SAndroid Build Coastguard Worker 					err = WSAIoctl( gInterfaceListChangedSocket, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
1378*48a54d36SAndroid Build Coastguard Worker 					if( err < 0 )
1379*48a54d36SAndroid Build Coastguard Worker 					{
1380*48a54d36SAndroid Build Coastguard Worker 						check( errno_compat() == WSAEWOULDBLOCK );
1381*48a54d36SAndroid Build Coastguard Worker 					}
1382*48a54d36SAndroid Build Coastguard Worker 				}
1383*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListComputerDescriptionEvent )
1384*48a54d36SAndroid Build Coastguard Worker 				{
1385*48a54d36SAndroid Build Coastguard Worker 					// The computer description might have changed
1386*48a54d36SAndroid Build Coastguard Worker 
1387*48a54d36SAndroid Build Coastguard Worker 					ComputerDescriptionDidChange( &gMDNSRecord );
1388*48a54d36SAndroid Build Coastguard Worker 					udsserver_handle_configchange( &gMDNSRecord );
1389*48a54d36SAndroid Build Coastguard Worker 
1390*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1391*48a54d36SAndroid Build Coastguard Worker 					if ( ( gDescKey != NULL ) && ( gDescChangedEvent != NULL ) )
1392*48a54d36SAndroid Build Coastguard Worker 					{
1393*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
1394*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1395*48a54d36SAndroid Build Coastguard Worker 					}
1396*48a54d36SAndroid Build Coastguard Worker 				}
1397*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListTCPIPEvent )
1398*48a54d36SAndroid Build Coastguard Worker 				{
1399*48a54d36SAndroid Build Coastguard Worker 					// The TCP/IP might have changed
1400*48a54d36SAndroid Build Coastguard Worker 
1401*48a54d36SAndroid Build Coastguard Worker 					TCPIPConfigDidChange( &gMDNSRecord );
1402*48a54d36SAndroid Build Coastguard Worker 					udsserver_handle_configchange( &gMDNSRecord );
1403*48a54d36SAndroid Build Coastguard Worker 
1404*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1405*48a54d36SAndroid Build Coastguard Worker 
1406*48a54d36SAndroid Build Coastguard Worker 					if ( ( gTcpipKey != NULL ) && ( gTcpipChangedEvent ) )
1407*48a54d36SAndroid Build Coastguard Worker 					{
1408*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE );
1409*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1410*48a54d36SAndroid Build Coastguard Worker 					}
1411*48a54d36SAndroid Build Coastguard Worker 				}
1412*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListDynDNSEvent )
1413*48a54d36SAndroid Build Coastguard Worker 				{
1414*48a54d36SAndroid Build Coastguard Worker 					// The DynDNS config might have changed
1415*48a54d36SAndroid Build Coastguard Worker 
1416*48a54d36SAndroid Build Coastguard Worker 					DynDNSConfigDidChange( &gMDNSRecord );
1417*48a54d36SAndroid Build Coastguard Worker 					udsserver_handle_configchange( &gMDNSRecord );
1418*48a54d36SAndroid Build Coastguard Worker 
1419*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1420*48a54d36SAndroid Build Coastguard Worker 
1421*48a54d36SAndroid Build Coastguard Worker 					if ((gDdnsKey != NULL) && (gDdnsChangedEvent))
1422*48a54d36SAndroid Build Coastguard Worker 					{
1423*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue(gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
1424*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1425*48a54d36SAndroid Build Coastguard Worker 					}
1426*48a54d36SAndroid Build Coastguard Worker 				}
1427*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListFileShareEvent )
1428*48a54d36SAndroid Build Coastguard Worker 				{
1429*48a54d36SAndroid Build Coastguard Worker 					// File sharing changed
1430*48a54d36SAndroid Build Coastguard Worker 
1431*48a54d36SAndroid Build Coastguard Worker 					FileSharingDidChange( &gMDNSRecord );
1432*48a54d36SAndroid Build Coastguard Worker 
1433*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1434*48a54d36SAndroid Build Coastguard Worker 
1435*48a54d36SAndroid Build Coastguard Worker 					if ((gFileSharingKey != NULL) && (gFileSharingChangedEvent))
1436*48a54d36SAndroid Build Coastguard Worker 					{
1437*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue(gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
1438*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1439*48a54d36SAndroid Build Coastguard Worker 					}
1440*48a54d36SAndroid Build Coastguard Worker 				}
1441*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListFirewallEvent )
1442*48a54d36SAndroid Build Coastguard Worker 				{
1443*48a54d36SAndroid Build Coastguard Worker 					// Firewall configuration changed
1444*48a54d36SAndroid Build Coastguard Worker 
1445*48a54d36SAndroid Build Coastguard Worker 					FirewallDidChange( &gMDNSRecord );
1446*48a54d36SAndroid Build Coastguard Worker 
1447*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1448*48a54d36SAndroid Build Coastguard Worker 
1449*48a54d36SAndroid Build Coastguard Worker 					if ((gFirewallKey != NULL) && (gFirewallChangedEvent))
1450*48a54d36SAndroid Build Coastguard Worker 					{
1451*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue(gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
1452*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1453*48a54d36SAndroid Build Coastguard Worker 					}
1454*48a54d36SAndroid Build Coastguard Worker 				}
1455*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListAdvertisedServicesEvent )
1456*48a54d36SAndroid Build Coastguard Worker 				{
1457*48a54d36SAndroid Build Coastguard Worker 					// Ultimately we'll want to manage multiple services, but right now the only service
1458*48a54d36SAndroid Build Coastguard Worker 					// we'll be managing is SMB.
1459*48a54d36SAndroid Build Coastguard Worker 
1460*48a54d36SAndroid Build Coastguard Worker 					FileSharingDidChange( &gMDNSRecord );
1461*48a54d36SAndroid Build Coastguard Worker 
1462*48a54d36SAndroid Build Coastguard Worker 					// and reset the event handler
1463*48a54d36SAndroid Build Coastguard Worker 
1464*48a54d36SAndroid Build Coastguard Worker 					if ( ( gAdvertisedServicesKey != NULL ) && ( gAdvertisedServicesChangedEvent ) )
1465*48a54d36SAndroid Build Coastguard Worker 					{
1466*48a54d36SAndroid Build Coastguard Worker 						err = RegNotifyChangeKeyValue(gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
1467*48a54d36SAndroid Build Coastguard Worker 						check_noerr( err );
1468*48a54d36SAndroid Build Coastguard Worker 					}
1469*48a54d36SAndroid Build Coastguard Worker 				}
1470*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListSPSWakeupEvent )
1471*48a54d36SAndroid Build Coastguard Worker 				{
1472*48a54d36SAndroid Build Coastguard Worker 					LARGE_INTEGER timeout;
1473*48a54d36SAndroid Build Coastguard Worker 
1474*48a54d36SAndroid Build Coastguard Worker 					ReportStatus( EVENTLOG_INFORMATION_TYPE, "Maintenance wake" );
1475*48a54d36SAndroid Build Coastguard Worker 
1476*48a54d36SAndroid Build Coastguard Worker 					timeout.QuadPart  = kSPSMaintenanceWakePeriod;
1477*48a54d36SAndroid Build Coastguard Worker 					timeout.QuadPart *= kSecondsTo100NSUnits;
1478*48a54d36SAndroid Build Coastguard Worker 
1479*48a54d36SAndroid Build Coastguard Worker 					SetWaitableTimer( gSPSSleepEvent, &timeout, 0, NULL, NULL, TRUE );
1480*48a54d36SAndroid Build Coastguard Worker 				}
1481*48a54d36SAndroid Build Coastguard Worker 				else if ( result == kWaitListSPSSleepEvent )
1482*48a54d36SAndroid Build Coastguard Worker 				{
1483*48a54d36SAndroid Build Coastguard Worker 					ReportStatus( EVENTLOG_INFORMATION_TYPE, "Returning to sleep after maintenance wake" );
1484*48a54d36SAndroid Build Coastguard Worker 
1485*48a54d36SAndroid Build Coastguard Worker 					// Calling SetSuspendState() doesn't invoke our sleep handlers, so we'll
1486*48a54d36SAndroid Build Coastguard Worker 					// call HandlePowerSuspend() explicity.  This will reset the
1487*48a54d36SAndroid Build Coastguard Worker 					// maintenance wake timers.
1488*48a54d36SAndroid Build Coastguard Worker 
1489*48a54d36SAndroid Build Coastguard Worker 					HandlePowerSuspend( NULL );
1490*48a54d36SAndroid Build Coastguard Worker 					SetSuspendState( FALSE, FALSE, FALSE );
1491*48a54d36SAndroid Build Coastguard Worker 				}
1492*48a54d36SAndroid Build Coastguard Worker 				else
1493*48a54d36SAndroid Build Coastguard Worker 				{
1494*48a54d36SAndroid Build Coastguard Worker 					int waitItemIndex;
1495*48a54d36SAndroid Build Coastguard Worker 
1496*48a54d36SAndroid Build Coastguard Worker 					waitItemIndex = (int)( ( (int) result ) - WAIT_OBJECT_0 );
1497*48a54d36SAndroid Build Coastguard Worker 					dlog( kDebugLevelChatty, DEBUG_NAME "waitable event on %d\n", waitItemIndex );
1498*48a54d36SAndroid Build Coastguard Worker 					check( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) );
1499*48a54d36SAndroid Build Coastguard Worker 
1500*48a54d36SAndroid Build Coastguard Worker 					if ( ( waitItemIndex >= 0 ) && ( waitItemIndex < waitListCount ) )
1501*48a54d36SAndroid Build Coastguard Worker 					{
1502*48a54d36SAndroid Build Coastguard Worker 						HANDLE	signaledEvent;
1503*48a54d36SAndroid Build Coastguard Worker 						int		n = 0;
1504*48a54d36SAndroid Build Coastguard Worker 
1505*48a54d36SAndroid Build Coastguard Worker 						signaledEvent = waitList[ waitItemIndex ];
1506*48a54d36SAndroid Build Coastguard Worker 
1507*48a54d36SAndroid Build Coastguard Worker 						// If gCurrentSource is not NULL, then this routine has been called
1508*48a54d36SAndroid Build Coastguard Worker 						// re-entrantly which should never happen.
1509*48a54d36SAndroid Build Coastguard Worker 
1510*48a54d36SAndroid Build Coastguard Worker 						check( !gCurrentSource );
1511*48a54d36SAndroid Build Coastguard Worker 
1512*48a54d36SAndroid Build Coastguard Worker 						for ( gCurrentSource = gEventSourceList; gCurrentSource; )
1513*48a54d36SAndroid Build Coastguard Worker 						{
1514*48a54d36SAndroid Build Coastguard Worker 							EventSource * current = gCurrentSource;
1515*48a54d36SAndroid Build Coastguard Worker 
1516*48a54d36SAndroid Build Coastguard Worker 							if ( gCurrentSource->event == signaledEvent )
1517*48a54d36SAndroid Build Coastguard Worker 							{
1518*48a54d36SAndroid Build Coastguard Worker 								gCurrentSource->handler( &gMDNSRecord, gCurrentSource->event, gCurrentSource->context );
1519*48a54d36SAndroid Build Coastguard Worker 								++n;
1520*48a54d36SAndroid Build Coastguard Worker 								break;
1521*48a54d36SAndroid Build Coastguard Worker 							}
1522*48a54d36SAndroid Build Coastguard Worker 
1523*48a54d36SAndroid Build Coastguard Worker 							// If the current node was removed as a result of calling
1524*48a54d36SAndroid Build Coastguard Worker 							// the handler, then gCurrentSource was already incremented to
1525*48a54d36SAndroid Build Coastguard Worker 							// the next node.  If it wasn't removed, then increment it
1526*48a54d36SAndroid Build Coastguard Worker 							// ourselves
1527*48a54d36SAndroid Build Coastguard Worker 
1528*48a54d36SAndroid Build Coastguard Worker 							if ( gCurrentSource == current )
1529*48a54d36SAndroid Build Coastguard Worker 							{
1530*48a54d36SAndroid Build Coastguard Worker 								gCurrentSource = gCurrentSource->next;
1531*48a54d36SAndroid Build Coastguard Worker 							}
1532*48a54d36SAndroid Build Coastguard Worker 						}
1533*48a54d36SAndroid Build Coastguard Worker 
1534*48a54d36SAndroid Build Coastguard Worker 						gCurrentSource = NULL;
1535*48a54d36SAndroid Build Coastguard Worker 
1536*48a54d36SAndroid Build Coastguard Worker 						check( n > 0 );
1537*48a54d36SAndroid Build Coastguard Worker 					}
1538*48a54d36SAndroid Build Coastguard Worker 					else
1539*48a54d36SAndroid Build Coastguard Worker 					{
1540*48a54d36SAndroid Build Coastguard Worker 						dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, result );
1541*48a54d36SAndroid Build Coastguard Worker 					}
1542*48a54d36SAndroid Build Coastguard Worker 				}
1543*48a54d36SAndroid Build Coastguard Worker 			}
1544*48a54d36SAndroid Build Coastguard Worker 			else
1545*48a54d36SAndroid Build Coastguard Worker 			{
1546*48a54d36SAndroid Build Coastguard Worker 				Sleep( 3 * 1000 );
1547*48a54d36SAndroid Build Coastguard Worker 
1548*48a54d36SAndroid Build Coastguard Worker 				err = SetupInterfaceList( &gMDNSRecord );
1549*48a54d36SAndroid Build Coastguard Worker 				check( !err );
1550*48a54d36SAndroid Build Coastguard Worker 
1551*48a54d36SAndroid Build Coastguard Worker 				err = uDNS_SetupDNSConfig( &gMDNSRecord );
1552*48a54d36SAndroid Build Coastguard Worker 				check( !err );
1553*48a54d36SAndroid Build Coastguard Worker 
1554*48a54d36SAndroid Build Coastguard Worker 				break;
1555*48a54d36SAndroid Build Coastguard Worker 			}
1556*48a54d36SAndroid Build Coastguard Worker 		}
1557*48a54d36SAndroid Build Coastguard Worker 
1558*48a54d36SAndroid Build Coastguard Worker 		if ( waitList )
1559*48a54d36SAndroid Build Coastguard Worker 		{
1560*48a54d36SAndroid Build Coastguard Worker 			free( waitList );
1561*48a54d36SAndroid Build Coastguard Worker 			waitList = NULL;
1562*48a54d36SAndroid Build Coastguard Worker 			waitListCount = 0;
1563*48a54d36SAndroid Build Coastguard Worker 		}
1564*48a54d36SAndroid Build Coastguard Worker 	}
1565*48a54d36SAndroid Build Coastguard Worker 
1566*48a54d36SAndroid Build Coastguard Worker exit:
1567*48a54d36SAndroid Build Coastguard Worker 
1568*48a54d36SAndroid Build Coastguard Worker 	return( 0 );
1569*48a54d36SAndroid Build Coastguard Worker }
1570*48a54d36SAndroid Build Coastguard Worker 
1571*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1572*48a54d36SAndroid Build Coastguard Worker //	ServiceSpecificStop
1573*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1574*48a54d36SAndroid Build Coastguard Worker 
ServiceSpecificStop(void)1575*48a54d36SAndroid Build Coastguard Worker static OSStatus	ServiceSpecificStop( void )
1576*48a54d36SAndroid Build Coastguard Worker {
1577*48a54d36SAndroid Build Coastguard Worker 	OSStatus	err;
1578*48a54d36SAndroid Build Coastguard Worker 	BOOL	 	ok;
1579*48a54d36SAndroid Build Coastguard Worker 
1580*48a54d36SAndroid Build Coastguard Worker 	ok = SetEvent(gStopEvent);
1581*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
1582*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1583*48a54d36SAndroid Build Coastguard Worker exit:
1584*48a54d36SAndroid Build Coastguard Worker 	return( err );
1585*48a54d36SAndroid Build Coastguard Worker }
1586*48a54d36SAndroid Build Coastguard Worker 
1587*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1588*48a54d36SAndroid Build Coastguard Worker //	ServiceSpecificFinalize
1589*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1590*48a54d36SAndroid Build Coastguard Worker 
ServiceSpecificFinalize(int argc,LPTSTR argv[])1591*48a54d36SAndroid Build Coastguard Worker static void	ServiceSpecificFinalize( int argc, LPTSTR argv[] )
1592*48a54d36SAndroid Build Coastguard Worker {
1593*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argc );
1594*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( argv );
1595*48a54d36SAndroid Build Coastguard Worker 
1596*48a54d36SAndroid Build Coastguard Worker 	//
1597*48a54d36SAndroid Build Coastguard Worker 	// clean up any open sessions
1598*48a54d36SAndroid Build Coastguard Worker 	//
1599*48a54d36SAndroid Build Coastguard Worker 	while ( gEventSourceList )
1600*48a54d36SAndroid Build Coastguard Worker 	{
1601*48a54d36SAndroid Build Coastguard Worker 		UnregisterWaitableEvent( &gMDNSRecord, gEventSourceList->event );
1602*48a54d36SAndroid Build Coastguard Worker 	}
1603*48a54d36SAndroid Build Coastguard Worker 
1604*48a54d36SAndroid Build Coastguard Worker 	//
1605*48a54d36SAndroid Build Coastguard Worker 	// clean up the notifications
1606*48a54d36SAndroid Build Coastguard Worker 	//
1607*48a54d36SAndroid Build Coastguard Worker 	TearDownNotifications();
1608*48a54d36SAndroid Build Coastguard Worker 
1609*48a54d36SAndroid Build Coastguard Worker 	//
1610*48a54d36SAndroid Build Coastguard Worker 	// clean up loaded library
1611*48a54d36SAndroid Build Coastguard Worker 	//
1612*48a54d36SAndroid Build Coastguard Worker 
1613*48a54d36SAndroid Build Coastguard Worker 	if( gIPHelperLibraryInstance )
1614*48a54d36SAndroid Build Coastguard Worker 	{
1615*48a54d36SAndroid Build Coastguard Worker 		gGetIpInterfaceEntryFunctionPtr = NULL;
1616*48a54d36SAndroid Build Coastguard Worker 
1617*48a54d36SAndroid Build Coastguard Worker 		FreeLibrary( gIPHelperLibraryInstance );
1618*48a54d36SAndroid Build Coastguard Worker 		gIPHelperLibraryInstance = NULL;
1619*48a54d36SAndroid Build Coastguard Worker 	}
1620*48a54d36SAndroid Build Coastguard Worker }
1621*48a54d36SAndroid Build Coastguard Worker 
1622*48a54d36SAndroid Build Coastguard Worker 
1623*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1624*48a54d36SAndroid Build Coastguard Worker //	SetupNotifications
1625*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1626*48a54d36SAndroid Build Coastguard Worker 
SetupNotifications()1627*48a54d36SAndroid Build Coastguard Worker mDNSlocal mStatus	SetupNotifications()
1628*48a54d36SAndroid Build Coastguard Worker {
1629*48a54d36SAndroid Build Coastguard Worker 	mStatus				err;
1630*48a54d36SAndroid Build Coastguard Worker 	SocketRef			sock;
1631*48a54d36SAndroid Build Coastguard Worker 	unsigned long		param;
1632*48a54d36SAndroid Build Coastguard Worker 	int					inBuffer;
1633*48a54d36SAndroid Build Coastguard Worker 	int					outBuffer;
1634*48a54d36SAndroid Build Coastguard Worker 	DWORD				outSize;
1635*48a54d36SAndroid Build Coastguard Worker 
1636*48a54d36SAndroid Build Coastguard Worker 	gStopEvent	=	CreateEvent(NULL, FALSE, FALSE, NULL);
1637*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gStopEvent, errno_compat(), kNoResourcesErr );
1638*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1639*48a54d36SAndroid Build Coastguard Worker 
1640*48a54d36SAndroid Build Coastguard Worker 	// Register to listen for address list changes.
1641*48a54d36SAndroid Build Coastguard Worker 
1642*48a54d36SAndroid Build Coastguard Worker 	gInterfaceListChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
1643*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gInterfaceListChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1644*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1645*48a54d36SAndroid Build Coastguard Worker 
1646*48a54d36SAndroid Build Coastguard Worker 	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
1647*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
1648*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1649*48a54d36SAndroid Build Coastguard Worker 	gInterfaceListChangedSocket = sock;
1650*48a54d36SAndroid Build Coastguard Worker 
1651*48a54d36SAndroid Build Coastguard Worker 	// Make the socket non-blocking so the WSAIoctl returns immediately with WSAEWOULDBLOCK. It will set the event
1652*48a54d36SAndroid Build Coastguard Worker 	// when a change to the interface list is detected.
1653*48a54d36SAndroid Build Coastguard Worker 
1654*48a54d36SAndroid Build Coastguard Worker 	param = 1;
1655*48a54d36SAndroid Build Coastguard Worker 	err = ioctlsocket( sock, FIONBIO, &param );
1656*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( err == 0, errno_compat(), kUnknownErr );
1657*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1658*48a54d36SAndroid Build Coastguard Worker 
1659*48a54d36SAndroid Build Coastguard Worker 	inBuffer	= 0;
1660*48a54d36SAndroid Build Coastguard Worker 	outBuffer	= 0;
1661*48a54d36SAndroid Build Coastguard Worker 	err = WSAIoctl( sock, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
1662*48a54d36SAndroid Build Coastguard Worker 	if( err < 0 )
1663*48a54d36SAndroid Build Coastguard Worker 	{
1664*48a54d36SAndroid Build Coastguard Worker 		check( errno_compat() == WSAEWOULDBLOCK );
1665*48a54d36SAndroid Build Coastguard Worker 	}
1666*48a54d36SAndroid Build Coastguard Worker 
1667*48a54d36SAndroid Build Coastguard Worker 	err = WSAEventSelect( sock, gInterfaceListChangedEvent, FD_ADDRESS_LIST_CHANGE );
1668*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( err == 0, errno_compat(), kUnknownErr );
1669*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1670*48a54d36SAndroid Build Coastguard Worker 
1671*48a54d36SAndroid Build Coastguard Worker 	gDescChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1672*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gDescChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1673*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1674*48a54d36SAndroid Build Coastguard Worker 
1675*48a54d36SAndroid Build Coastguard Worker 	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters"), 0, KEY_READ, &gDescKey);
1676*48a54d36SAndroid Build Coastguard Worker 	check_translated_errno( err == 0, errno_compat(), kNameErr );
1677*48a54d36SAndroid Build Coastguard Worker 
1678*48a54d36SAndroid Build Coastguard Worker 	if ( gDescKey != NULL )
1679*48a54d36SAndroid Build Coastguard Worker 	{
1680*48a54d36SAndroid Build Coastguard Worker 		err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
1681*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
1682*48a54d36SAndroid Build Coastguard Worker 	}
1683*48a54d36SAndroid Build Coastguard Worker 
1684*48a54d36SAndroid Build Coastguard Worker 	// This will catch all changes to tcp/ip networking, including changes to the domain search list
1685*48a54d36SAndroid Build Coastguard Worker 
1686*48a54d36SAndroid Build Coastguard Worker 	gTcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1687*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gTcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1688*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1689*48a54d36SAndroid Build Coastguard Worker 
1690*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &gTcpipKey );
1691*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1692*48a54d36SAndroid Build Coastguard Worker 
1693*48a54d36SAndroid Build Coastguard Worker 	err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE);
1694*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1695*48a54d36SAndroid Build Coastguard Worker 
1696*48a54d36SAndroid Build Coastguard Worker 	// This will catch all changes to ddns configuration
1697*48a54d36SAndroid Build Coastguard Worker 
1698*48a54d36SAndroid Build Coastguard Worker 	gDdnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1699*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gDdnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1700*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1701*48a54d36SAndroid Build Coastguard Worker 
1702*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup"), &gDdnsKey );
1703*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1704*48a54d36SAndroid Build Coastguard Worker 
1705*48a54d36SAndroid Build Coastguard Worker 	err = RegNotifyChangeKeyValue( gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
1706*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1707*48a54d36SAndroid Build Coastguard Worker 
1708*48a54d36SAndroid Build Coastguard Worker 	// This will catch all changes to file sharing
1709*48a54d36SAndroid Build Coastguard Worker 
1710*48a54d36SAndroid Build Coastguard Worker 	gFileSharingChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
1711*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gFileSharingChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1712*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1713*48a54d36SAndroid Build Coastguard Worker 
1714*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), &gFileSharingKey );
1715*48a54d36SAndroid Build Coastguard Worker 
1716*48a54d36SAndroid Build Coastguard Worker 	// Just to make sure that initialization doesn't fail on some old OS
1717*48a54d36SAndroid Build Coastguard Worker 	// that doesn't have this key, we'll only add the notification if
1718*48a54d36SAndroid Build Coastguard Worker 	// the key exists.
1719*48a54d36SAndroid Build Coastguard Worker 
1720*48a54d36SAndroid Build Coastguard Worker 	if ( !err )
1721*48a54d36SAndroid Build Coastguard Worker 	{
1722*48a54d36SAndroid Build Coastguard Worker 		err = RegNotifyChangeKeyValue( gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
1723*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
1724*48a54d36SAndroid Build Coastguard Worker 	}
1725*48a54d36SAndroid Build Coastguard Worker 	else
1726*48a54d36SAndroid Build Coastguard Worker 	{
1727*48a54d36SAndroid Build Coastguard Worker 		err = mStatus_NoError;
1728*48a54d36SAndroid Build Coastguard Worker 	}
1729*48a54d36SAndroid Build Coastguard Worker 
1730*48a54d36SAndroid Build Coastguard Worker 	// This will catch changes to the Windows firewall
1731*48a54d36SAndroid Build Coastguard Worker 
1732*48a54d36SAndroid Build Coastguard Worker 	gFirewallChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
1733*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gFirewallChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1734*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1735*48a54d36SAndroid Build Coastguard Worker 
1736*48a54d36SAndroid Build Coastguard Worker 	// Just to make sure that initialization doesn't fail on some old OS
1737*48a54d36SAndroid Build Coastguard Worker 	// that doesn't have this key, we'll only add the notification if
1738*48a54d36SAndroid Build Coastguard Worker 	// the key exists.
1739*48a54d36SAndroid Build Coastguard Worker 
1740*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules"), &gFirewallKey );
1741*48a54d36SAndroid Build Coastguard Worker 
1742*48a54d36SAndroid Build Coastguard Worker 	if ( !err )
1743*48a54d36SAndroid Build Coastguard Worker 	{
1744*48a54d36SAndroid Build Coastguard Worker 		err = RegNotifyChangeKeyValue( gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
1745*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
1746*48a54d36SAndroid Build Coastguard Worker 	}
1747*48a54d36SAndroid Build Coastguard Worker 	else
1748*48a54d36SAndroid Build Coastguard Worker 	{
1749*48a54d36SAndroid Build Coastguard Worker 		err = mStatus_NoError;
1750*48a54d36SAndroid Build Coastguard Worker 	}
1751*48a54d36SAndroid Build Coastguard Worker 
1752*48a54d36SAndroid Build Coastguard Worker 	// This will catch all changes to advertised services configuration
1753*48a54d36SAndroid Build Coastguard Worker 
1754*48a54d36SAndroid Build Coastguard Worker 	gAdvertisedServicesChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1755*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gAdvertisedServicesChangedEvent, (mStatus) GetLastError(), kUnknownErr );
1756*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1757*48a54d36SAndroid Build Coastguard Worker 
1758*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\Services"), &gAdvertisedServicesKey );
1759*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1760*48a54d36SAndroid Build Coastguard Worker 
1761*48a54d36SAndroid Build Coastguard Worker 	err = RegNotifyChangeKeyValue( gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
1762*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1763*48a54d36SAndroid Build Coastguard Worker 
1764*48a54d36SAndroid Build Coastguard Worker 	gSPSWakeupEvent = CreateWaitableTimer( NULL, FALSE, NULL );
1765*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gSPSWakeupEvent, (mStatus) GetLastError(), kUnknownErr );
1766*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1767*48a54d36SAndroid Build Coastguard Worker 
1768*48a54d36SAndroid Build Coastguard Worker 	gSPSSleepEvent = CreateWaitableTimer( NULL, FALSE, NULL );
1769*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gSPSSleepEvent, (mStatus) GetLastError(), kUnknownErr );
1770*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1771*48a54d36SAndroid Build Coastguard Worker 
1772*48a54d36SAndroid Build Coastguard Worker 	gUDSEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
1773*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( gUDSEvent, ( mStatus ) GetLastError(), kUnknownErr );
1774*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
1775*48a54d36SAndroid Build Coastguard Worker 
1776*48a54d36SAndroid Build Coastguard Worker exit:
1777*48a54d36SAndroid Build Coastguard Worker 	if( err )
1778*48a54d36SAndroid Build Coastguard Worker 	{
1779*48a54d36SAndroid Build Coastguard Worker 		TearDownNotifications();
1780*48a54d36SAndroid Build Coastguard Worker 	}
1781*48a54d36SAndroid Build Coastguard Worker 	return( err );
1782*48a54d36SAndroid Build Coastguard Worker }
1783*48a54d36SAndroid Build Coastguard Worker 
1784*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1785*48a54d36SAndroid Build Coastguard Worker //	TearDownNotifications
1786*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1787*48a54d36SAndroid Build Coastguard Worker 
TearDownNotifications()1788*48a54d36SAndroid Build Coastguard Worker mDNSlocal mStatus	TearDownNotifications()
1789*48a54d36SAndroid Build Coastguard Worker {
1790*48a54d36SAndroid Build Coastguard Worker 	if ( gStopEvent )
1791*48a54d36SAndroid Build Coastguard Worker 	{
1792*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gStopEvent );
1793*48a54d36SAndroid Build Coastguard Worker 		gStopEvent = NULL;
1794*48a54d36SAndroid Build Coastguard Worker 	}
1795*48a54d36SAndroid Build Coastguard Worker 
1796*48a54d36SAndroid Build Coastguard Worker 	if( IsValidSocket( gInterfaceListChangedSocket ) )
1797*48a54d36SAndroid Build Coastguard Worker 	{
1798*48a54d36SAndroid Build Coastguard Worker 		close_compat( gInterfaceListChangedSocket );
1799*48a54d36SAndroid Build Coastguard Worker 		gInterfaceListChangedSocket = kInvalidSocketRef;
1800*48a54d36SAndroid Build Coastguard Worker 	}
1801*48a54d36SAndroid Build Coastguard Worker 
1802*48a54d36SAndroid Build Coastguard Worker 	if( gInterfaceListChangedEvent )
1803*48a54d36SAndroid Build Coastguard Worker 	{
1804*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gInterfaceListChangedEvent );
1805*48a54d36SAndroid Build Coastguard Worker 		gInterfaceListChangedEvent = 0;
1806*48a54d36SAndroid Build Coastguard Worker 	}
1807*48a54d36SAndroid Build Coastguard Worker 
1808*48a54d36SAndroid Build Coastguard Worker 	if ( gDescChangedEvent != NULL )
1809*48a54d36SAndroid Build Coastguard Worker 	{
1810*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gDescChangedEvent );
1811*48a54d36SAndroid Build Coastguard Worker 		gDescChangedEvent = NULL;
1812*48a54d36SAndroid Build Coastguard Worker 	}
1813*48a54d36SAndroid Build Coastguard Worker 
1814*48a54d36SAndroid Build Coastguard Worker 	if ( gDescKey != NULL )
1815*48a54d36SAndroid Build Coastguard Worker 	{
1816*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( gDescKey );
1817*48a54d36SAndroid Build Coastguard Worker 		gDescKey = NULL;
1818*48a54d36SAndroid Build Coastguard Worker 	}
1819*48a54d36SAndroid Build Coastguard Worker 
1820*48a54d36SAndroid Build Coastguard Worker 	if ( gTcpipChangedEvent != NULL )
1821*48a54d36SAndroid Build Coastguard Worker 	{
1822*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gTcpipChangedEvent );
1823*48a54d36SAndroid Build Coastguard Worker 		gTcpipChangedEvent = NULL;
1824*48a54d36SAndroid Build Coastguard Worker 	}
1825*48a54d36SAndroid Build Coastguard Worker 
1826*48a54d36SAndroid Build Coastguard Worker 	if ( gDdnsChangedEvent != NULL )
1827*48a54d36SAndroid Build Coastguard Worker 	{
1828*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gDdnsChangedEvent );
1829*48a54d36SAndroid Build Coastguard Worker 		gDdnsChangedEvent = NULL;
1830*48a54d36SAndroid Build Coastguard Worker 	}
1831*48a54d36SAndroid Build Coastguard Worker 
1832*48a54d36SAndroid Build Coastguard Worker 	if ( gDdnsKey != NULL )
1833*48a54d36SAndroid Build Coastguard Worker 	{
1834*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( gDdnsKey );
1835*48a54d36SAndroid Build Coastguard Worker 		gDdnsKey = NULL;
1836*48a54d36SAndroid Build Coastguard Worker 	}
1837*48a54d36SAndroid Build Coastguard Worker 
1838*48a54d36SAndroid Build Coastguard Worker 	if ( gFileSharingChangedEvent != NULL )
1839*48a54d36SAndroid Build Coastguard Worker 	{
1840*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gFileSharingChangedEvent );
1841*48a54d36SAndroid Build Coastguard Worker 		gFileSharingChangedEvent = NULL;
1842*48a54d36SAndroid Build Coastguard Worker 	}
1843*48a54d36SAndroid Build Coastguard Worker 
1844*48a54d36SAndroid Build Coastguard Worker 	if ( gFileSharingKey != NULL )
1845*48a54d36SAndroid Build Coastguard Worker 	{
1846*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( gFileSharingKey );
1847*48a54d36SAndroid Build Coastguard Worker 		gFileSharingKey = NULL;
1848*48a54d36SAndroid Build Coastguard Worker 	}
1849*48a54d36SAndroid Build Coastguard Worker 
1850*48a54d36SAndroid Build Coastguard Worker 	if ( gFirewallChangedEvent != NULL )
1851*48a54d36SAndroid Build Coastguard Worker 	{
1852*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gFirewallChangedEvent );
1853*48a54d36SAndroid Build Coastguard Worker 		gFirewallChangedEvent = NULL;
1854*48a54d36SAndroid Build Coastguard Worker 	}
1855*48a54d36SAndroid Build Coastguard Worker 
1856*48a54d36SAndroid Build Coastguard Worker 	if ( gFirewallKey != NULL )
1857*48a54d36SAndroid Build Coastguard Worker 	{
1858*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( gFirewallKey );
1859*48a54d36SAndroid Build Coastguard Worker 		gFirewallKey = NULL;
1860*48a54d36SAndroid Build Coastguard Worker 	}
1861*48a54d36SAndroid Build Coastguard Worker 
1862*48a54d36SAndroid Build Coastguard Worker 	if ( gAdvertisedServicesChangedEvent != NULL )
1863*48a54d36SAndroid Build Coastguard Worker 	{
1864*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gAdvertisedServicesChangedEvent );
1865*48a54d36SAndroid Build Coastguard Worker 		gAdvertisedServicesChangedEvent = NULL;
1866*48a54d36SAndroid Build Coastguard Worker 	}
1867*48a54d36SAndroid Build Coastguard Worker 
1868*48a54d36SAndroid Build Coastguard Worker 	if ( gAdvertisedServicesKey != NULL )
1869*48a54d36SAndroid Build Coastguard Worker 	{
1870*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( gAdvertisedServicesKey );
1871*48a54d36SAndroid Build Coastguard Worker 		gAdvertisedServicesKey = NULL;
1872*48a54d36SAndroid Build Coastguard Worker 	}
1873*48a54d36SAndroid Build Coastguard Worker 
1874*48a54d36SAndroid Build Coastguard Worker 	if ( gSPSWakeupEvent )
1875*48a54d36SAndroid Build Coastguard Worker 	{
1876*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gSPSWakeupEvent );
1877*48a54d36SAndroid Build Coastguard Worker 		gSPSWakeupEvent = NULL;
1878*48a54d36SAndroid Build Coastguard Worker 	}
1879*48a54d36SAndroid Build Coastguard Worker 
1880*48a54d36SAndroid Build Coastguard Worker 	if ( gSPSSleepEvent )
1881*48a54d36SAndroid Build Coastguard Worker 	{
1882*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gSPSSleepEvent );
1883*48a54d36SAndroid Build Coastguard Worker 		gSPSSleepEvent = NULL;
1884*48a54d36SAndroid Build Coastguard Worker 	}
1885*48a54d36SAndroid Build Coastguard Worker 
1886*48a54d36SAndroid Build Coastguard Worker 	return( mStatus_NoError );
1887*48a54d36SAndroid Build Coastguard Worker }
1888*48a54d36SAndroid Build Coastguard Worker 
1889*48a54d36SAndroid Build Coastguard Worker 
1890*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1891*48a54d36SAndroid Build Coastguard Worker //	RegisterWaitableEvent
1892*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1893*48a54d36SAndroid Build Coastguard Worker 
RegisterWaitableEvent(mDNS * const inMDNS,HANDLE event,void * context,RegisterWaitableEventHandler handler)1894*48a54d36SAndroid Build Coastguard Worker static mStatus RegisterWaitableEvent( mDNS * const inMDNS, HANDLE event, void * context, RegisterWaitableEventHandler handler )
1895*48a54d36SAndroid Build Coastguard Worker {
1896*48a54d36SAndroid Build Coastguard Worker 	EventSource * source;
1897*48a54d36SAndroid Build Coastguard Worker 	mStatus err = mStatus_NoError;
1898*48a54d36SAndroid Build Coastguard Worker 
1899*48a54d36SAndroid Build Coastguard Worker 	( void ) inMDNS;
1900*48a54d36SAndroid Build Coastguard Worker 	check( event );
1901*48a54d36SAndroid Build Coastguard Worker 	check( handler );
1902*48a54d36SAndroid Build Coastguard Worker 
1903*48a54d36SAndroid Build Coastguard Worker 	source = ( EventSource* ) malloc( sizeof( EventSource ) );
1904*48a54d36SAndroid Build Coastguard Worker 	require_action( source, exit, err = mStatus_NoMemoryErr );
1905*48a54d36SAndroid Build Coastguard Worker 	mDNSPlatformMemZero( source, sizeof( EventSource ) );
1906*48a54d36SAndroid Build Coastguard Worker 	source->event = event;
1907*48a54d36SAndroid Build Coastguard Worker 	source->context = context;
1908*48a54d36SAndroid Build Coastguard Worker 	source->handler = handler;
1909*48a54d36SAndroid Build Coastguard Worker 
1910*48a54d36SAndroid Build Coastguard Worker 	source->next			= gEventSourceList;
1911*48a54d36SAndroid Build Coastguard Worker 	gEventSourceList		= source;
1912*48a54d36SAndroid Build Coastguard Worker 	gEventSourceListChanged	= TRUE;
1913*48a54d36SAndroid Build Coastguard Worker 	gEventSources++;
1914*48a54d36SAndroid Build Coastguard Worker 
1915*48a54d36SAndroid Build Coastguard Worker exit:
1916*48a54d36SAndroid Build Coastguard Worker 
1917*48a54d36SAndroid Build Coastguard Worker 	return err;
1918*48a54d36SAndroid Build Coastguard Worker }
1919*48a54d36SAndroid Build Coastguard Worker 
1920*48a54d36SAndroid Build Coastguard Worker 
1921*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1922*48a54d36SAndroid Build Coastguard Worker //	UnregisterWaitableEvent
1923*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1924*48a54d36SAndroid Build Coastguard Worker 
UnregisterWaitableEvent(mDNS * const inMDNS,HANDLE event)1925*48a54d36SAndroid Build Coastguard Worker static void UnregisterWaitableEvent( mDNS * const inMDNS, HANDLE event )
1926*48a54d36SAndroid Build Coastguard Worker {
1927*48a54d36SAndroid Build Coastguard Worker 	EventSource	*	current	= gEventSourceList;
1928*48a54d36SAndroid Build Coastguard Worker 	EventSource	*	last	= NULL;
1929*48a54d36SAndroid Build Coastguard Worker 
1930*48a54d36SAndroid Build Coastguard Worker 	( void ) inMDNS;
1931*48a54d36SAndroid Build Coastguard Worker 	check( event );
1932*48a54d36SAndroid Build Coastguard Worker 
1933*48a54d36SAndroid Build Coastguard Worker 	while ( current )
1934*48a54d36SAndroid Build Coastguard Worker 	{
1935*48a54d36SAndroid Build Coastguard Worker 		if ( current->event == event )
1936*48a54d36SAndroid Build Coastguard Worker 		{
1937*48a54d36SAndroid Build Coastguard Worker 			if ( last == NULL )
1938*48a54d36SAndroid Build Coastguard Worker 			{
1939*48a54d36SAndroid Build Coastguard Worker 				gEventSourceList = current->next;
1940*48a54d36SAndroid Build Coastguard Worker 			}
1941*48a54d36SAndroid Build Coastguard Worker 			else
1942*48a54d36SAndroid Build Coastguard Worker 			{
1943*48a54d36SAndroid Build Coastguard Worker 				last->next = current->next;
1944*48a54d36SAndroid Build Coastguard Worker 			}
1945*48a54d36SAndroid Build Coastguard Worker 
1946*48a54d36SAndroid Build Coastguard Worker 			gEventSourceListChanged = TRUE;
1947*48a54d36SAndroid Build Coastguard Worker 
1948*48a54d36SAndroid Build Coastguard Worker 			// Protect against removing the node that we happen
1949*48a54d36SAndroid Build Coastguard Worker 			// to be looking at as we iterate through the event
1950*48a54d36SAndroid Build Coastguard Worker 			// source list in ServiceSpecificRun()
1951*48a54d36SAndroid Build Coastguard Worker 
1952*48a54d36SAndroid Build Coastguard Worker 			if ( current == gCurrentSource )
1953*48a54d36SAndroid Build Coastguard Worker 			{
1954*48a54d36SAndroid Build Coastguard Worker 				gCurrentSource = current->next;
1955*48a54d36SAndroid Build Coastguard Worker 			}
1956*48a54d36SAndroid Build Coastguard Worker 
1957*48a54d36SAndroid Build Coastguard Worker 			gEventSources--;
1958*48a54d36SAndroid Build Coastguard Worker 			free( current );
1959*48a54d36SAndroid Build Coastguard Worker 
1960*48a54d36SAndroid Build Coastguard Worker 			break;
1961*48a54d36SAndroid Build Coastguard Worker 		}
1962*48a54d36SAndroid Build Coastguard Worker 
1963*48a54d36SAndroid Build Coastguard Worker 		last	= current;
1964*48a54d36SAndroid Build Coastguard Worker 		current	= current->next;
1965*48a54d36SAndroid Build Coastguard Worker 	}
1966*48a54d36SAndroid Build Coastguard Worker }
1967*48a54d36SAndroid Build Coastguard Worker 
1968*48a54d36SAndroid Build Coastguard Worker 
1969*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1970*48a54d36SAndroid Build Coastguard Worker //	SetupWaitList
1971*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
1972*48a54d36SAndroid Build Coastguard Worker 
SetupWaitList(mDNS * const inMDNS,HANDLE ** outWaitList,int * outWaitListCount)1973*48a54d36SAndroid Build Coastguard Worker mDNSlocal mStatus SetupWaitList( mDNS * const inMDNS, HANDLE **outWaitList, int *outWaitListCount )
1974*48a54d36SAndroid Build Coastguard Worker {
1975*48a54d36SAndroid Build Coastguard Worker 	int				waitListCount;
1976*48a54d36SAndroid Build Coastguard Worker 	HANDLE		*	waitList;
1977*48a54d36SAndroid Build Coastguard Worker 	HANDLE		*	waitItemPtr;
1978*48a54d36SAndroid Build Coastguard Worker 	EventSource	*	source;
1979*48a54d36SAndroid Build Coastguard Worker 	mStatus			err;
1980*48a54d36SAndroid Build Coastguard Worker 
1981*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up wait list\n" );
1982*48a54d36SAndroid Build Coastguard Worker 
1983*48a54d36SAndroid Build Coastguard Worker 	( void ) inMDNS;
1984*48a54d36SAndroid Build Coastguard Worker 	check( inMDNS->p );
1985*48a54d36SAndroid Build Coastguard Worker 	check( outWaitList );
1986*48a54d36SAndroid Build Coastguard Worker 	check( outWaitListCount );
1987*48a54d36SAndroid Build Coastguard Worker 
1988*48a54d36SAndroid Build Coastguard Worker 	// Allocate an array to hold all the objects to wait on.
1989*48a54d36SAndroid Build Coastguard Worker 
1990*48a54d36SAndroid Build Coastguard Worker 	waitListCount = kWaitListFixedItemCount + gEventSources;
1991*48a54d36SAndroid Build Coastguard Worker 	waitList = ( HANDLE* ) malloc( waitListCount * sizeof( *waitList ) );
1992*48a54d36SAndroid Build Coastguard Worker 	require_action( waitList, exit, err = mStatus_NoMemoryErr );
1993*48a54d36SAndroid Build Coastguard Worker 	waitItemPtr = waitList;
1994*48a54d36SAndroid Build Coastguard Worker 
1995*48a54d36SAndroid Build Coastguard Worker 	// Add the fixed wait items to the beginning of the list.
1996*48a54d36SAndroid Build Coastguard Worker 
1997*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gStopEvent;
1998*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gInterfaceListChangedEvent;
1999*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gDescChangedEvent;
2000*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gTcpipChangedEvent;
2001*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gDdnsChangedEvent;
2002*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gFileSharingChangedEvent;
2003*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gFirewallChangedEvent;
2004*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gAdvertisedServicesChangedEvent;
2005*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gSPSWakeupEvent;
2006*48a54d36SAndroid Build Coastguard Worker 	*waitItemPtr++	=	gSPSSleepEvent;
2007*48a54d36SAndroid Build Coastguard Worker 
2008*48a54d36SAndroid Build Coastguard Worker 	for ( source = gEventSourceList; source; source = source->next )
2009*48a54d36SAndroid Build Coastguard Worker 	{
2010*48a54d36SAndroid Build Coastguard Worker 		*waitItemPtr++ = source->event;
2011*48a54d36SAndroid Build Coastguard Worker 	}
2012*48a54d36SAndroid Build Coastguard Worker 
2013*48a54d36SAndroid Build Coastguard Worker 	check( ( int )( waitItemPtr - waitList ) == waitListCount );
2014*48a54d36SAndroid Build Coastguard Worker 
2015*48a54d36SAndroid Build Coastguard Worker 	*outWaitList 		= waitList;
2016*48a54d36SAndroid Build Coastguard Worker 	*outWaitListCount	= waitListCount;
2017*48a54d36SAndroid Build Coastguard Worker 	waitList			= NULL;
2018*48a54d36SAndroid Build Coastguard Worker 	err					= mStatus_NoError;
2019*48a54d36SAndroid Build Coastguard Worker 
2020*48a54d36SAndroid Build Coastguard Worker exit:
2021*48a54d36SAndroid Build Coastguard Worker 
2022*48a54d36SAndroid Build Coastguard Worker 	if( waitList )
2023*48a54d36SAndroid Build Coastguard Worker 	{
2024*48a54d36SAndroid Build Coastguard Worker 		free( waitList );
2025*48a54d36SAndroid Build Coastguard Worker 	}
2026*48a54d36SAndroid Build Coastguard Worker 
2027*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up wait list done (err=%d %m)\n", err, err );
2028*48a54d36SAndroid Build Coastguard Worker 	return( err );
2029*48a54d36SAndroid Build Coastguard Worker }
2030*48a54d36SAndroid Build Coastguard Worker 
2031*48a54d36SAndroid Build Coastguard Worker 
2032*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2033*48a54d36SAndroid Build Coastguard Worker //	CoreCallback
2034*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2035*48a54d36SAndroid Build Coastguard Worker 
2036*48a54d36SAndroid Build Coastguard Worker static void
CoreCallback(mDNS * const inMDNS,mStatus status)2037*48a54d36SAndroid Build Coastguard Worker CoreCallback(mDNS * const inMDNS, mStatus status)
2038*48a54d36SAndroid Build Coastguard Worker {
2039*48a54d36SAndroid Build Coastguard Worker 	if (status == mStatus_ConfigChanged)
2040*48a54d36SAndroid Build Coastguard Worker 	{
2041*48a54d36SAndroid Build Coastguard Worker 		SetLLRoute( inMDNS );
2042*48a54d36SAndroid Build Coastguard Worker 	}
2043*48a54d36SAndroid Build Coastguard Worker }
2044*48a54d36SAndroid Build Coastguard Worker 
2045*48a54d36SAndroid Build Coastguard Worker 
2046*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2047*48a54d36SAndroid Build Coastguard Worker //	UDSCanAccept
2048*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2049*48a54d36SAndroid Build Coastguard Worker 
UDSCanAccept(mDNS * const inMDNS,HANDLE event,void * context)2050*48a54d36SAndroid Build Coastguard Worker mDNSlocal void UDSCanAccept( mDNS * const inMDNS, HANDLE event, void * context )
2051*48a54d36SAndroid Build Coastguard Worker {
2052*48a54d36SAndroid Build Coastguard Worker 	( void ) inMDNS;
2053*48a54d36SAndroid Build Coastguard Worker 	( void ) event;
2054*48a54d36SAndroid Build Coastguard Worker 
2055*48a54d36SAndroid Build Coastguard Worker 	if ( gUDSCallback )
2056*48a54d36SAndroid Build Coastguard Worker 	{
2057*48a54d36SAndroid Build Coastguard Worker 		gUDSCallback( ( int ) gUDSSocket, 0, context );
2058*48a54d36SAndroid Build Coastguard Worker 	}
2059*48a54d36SAndroid Build Coastguard Worker }
2060*48a54d36SAndroid Build Coastguard Worker 
2061*48a54d36SAndroid Build Coastguard Worker 
2062*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2063*48a54d36SAndroid Build Coastguard Worker //	UDSCanRead
2064*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2065*48a54d36SAndroid Build Coastguard Worker 
UDSCanRead(TCPSocket * sock)2066*48a54d36SAndroid Build Coastguard Worker mDNSlocal void UDSCanRead( TCPSocket * sock )
2067*48a54d36SAndroid Build Coastguard Worker {
2068*48a54d36SAndroid Build Coastguard Worker 	udsEventCallback callback = ( udsEventCallback ) sock->userCallback;
2069*48a54d36SAndroid Build Coastguard Worker 
2070*48a54d36SAndroid Build Coastguard Worker 	if ( callback )
2071*48a54d36SAndroid Build Coastguard Worker 	{
2072*48a54d36SAndroid Build Coastguard Worker 		callback( (int) sock->fd, 0, sock->userContext );
2073*48a54d36SAndroid Build Coastguard Worker 	}
2074*48a54d36SAndroid Build Coastguard Worker }
2075*48a54d36SAndroid Build Coastguard Worker 
2076*48a54d36SAndroid Build Coastguard Worker 
2077*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2078*48a54d36SAndroid Build Coastguard Worker //	udsSupportAddFDToEventLoop
2079*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2080*48a54d36SAndroid Build Coastguard Worker 
2081*48a54d36SAndroid Build Coastguard Worker 
2082*48a54d36SAndroid Build Coastguard Worker mStatus
udsSupportAddFDToEventLoop(SocketRef fd,udsEventCallback callback,void * context,void ** platform_data)2083*48a54d36SAndroid Build Coastguard Worker udsSupportAddFDToEventLoop( SocketRef fd, udsEventCallback callback, void *context, void **platform_data)
2084*48a54d36SAndroid Build Coastguard Worker {
2085*48a54d36SAndroid Build Coastguard Worker 	mStatus err = mStatus_NoError;
2086*48a54d36SAndroid Build Coastguard Worker 
2087*48a54d36SAndroid Build Coastguard Worker 	// We are using some knowledge of what is being passed to us here.  If the fd is a listen socket,
2088*48a54d36SAndroid Build Coastguard Worker 	// then the "callback" parameter is NULL.  If it is an actual read/write socket, then the "callback"
2089*48a54d36SAndroid Build Coastguard Worker 	// parameter is not null. This is important because we use waitable events for the listen socket
2090*48a54d36SAndroid Build Coastguard Worker 	// and alertable I/O for the read/write sockets.
2091*48a54d36SAndroid Build Coastguard Worker 
2092*48a54d36SAndroid Build Coastguard Worker 	if ( context )
2093*48a54d36SAndroid Build Coastguard Worker 	{
2094*48a54d36SAndroid Build Coastguard Worker 		TCPSocket * sock;
2095*48a54d36SAndroid Build Coastguard Worker 
2096*48a54d36SAndroid Build Coastguard Worker 		sock = malloc( sizeof( TCPSocket ) );
2097*48a54d36SAndroid Build Coastguard Worker 		require_action( sock, exit, err = mStatus_NoMemoryErr );
2098*48a54d36SAndroid Build Coastguard Worker 		mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
2099*48a54d36SAndroid Build Coastguard Worker 
2100*48a54d36SAndroid Build Coastguard Worker 		sock->fd				= (SOCKET) fd;
2101*48a54d36SAndroid Build Coastguard Worker 		sock->readEventHandler	= UDSCanRead;
2102*48a54d36SAndroid Build Coastguard Worker 		sock->userCallback		= callback;
2103*48a54d36SAndroid Build Coastguard Worker 		sock->userContext		= context;
2104*48a54d36SAndroid Build Coastguard Worker 		sock->m					= &gMDNSRecord;
2105*48a54d36SAndroid Build Coastguard Worker 
2106*48a54d36SAndroid Build Coastguard Worker 		err = TCPAddSocket( sock->m, sock );
2107*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2108*48a54d36SAndroid Build Coastguard Worker 
2109*48a54d36SAndroid Build Coastguard Worker 		*platform_data = sock;
2110*48a54d36SAndroid Build Coastguard Worker 	}
2111*48a54d36SAndroid Build Coastguard Worker 	else
2112*48a54d36SAndroid Build Coastguard Worker 	{
2113*48a54d36SAndroid Build Coastguard Worker 		gUDSSocket		= fd;
2114*48a54d36SAndroid Build Coastguard Worker 		gUDSCallback	= callback;
2115*48a54d36SAndroid Build Coastguard Worker 		gUDSEvent		= CreateEvent( NULL, FALSE, FALSE, NULL );
2116*48a54d36SAndroid Build Coastguard Worker 		err = translate_errno( gUDSEvent, (mStatus) GetLastError(), kUnknownErr );
2117*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2118*48a54d36SAndroid Build Coastguard Worker 		err = WSAEventSelect( fd, gUDSEvent, FD_ACCEPT | FD_CLOSE );
2119*48a54d36SAndroid Build Coastguard Worker 		err = translate_errno( err == 0, WSAGetLastError(), kNoResourcesErr );
2120*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2121*48a54d36SAndroid Build Coastguard Worker 		err = RegisterWaitableEvent( &gMDNSRecord, gUDSEvent, context, UDSCanAccept );
2122*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2123*48a54d36SAndroid Build Coastguard Worker 	}
2124*48a54d36SAndroid Build Coastguard Worker 
2125*48a54d36SAndroid Build Coastguard Worker exit:
2126*48a54d36SAndroid Build Coastguard Worker 
2127*48a54d36SAndroid Build Coastguard Worker 	return err;
2128*48a54d36SAndroid Build Coastguard Worker }
2129*48a54d36SAndroid Build Coastguard Worker 
2130*48a54d36SAndroid Build Coastguard Worker 
2131*48a54d36SAndroid Build Coastguard Worker int
udsSupportReadFD(SocketRef fd,char * buf,int len,int flags,void * platform_data)2132*48a54d36SAndroid Build Coastguard Worker udsSupportReadFD( SocketRef fd, char *buf, int len, int flags, void *platform_data )
2133*48a54d36SAndroid Build Coastguard Worker {
2134*48a54d36SAndroid Build Coastguard Worker 	TCPSocket	*	sock;
2135*48a54d36SAndroid Build Coastguard Worker 	mDNSBool		closed;
2136*48a54d36SAndroid Build Coastguard Worker 	int				ret;
2137*48a54d36SAndroid Build Coastguard Worker 
2138*48a54d36SAndroid Build Coastguard Worker 	( void ) flags;
2139*48a54d36SAndroid Build Coastguard Worker 
2140*48a54d36SAndroid Build Coastguard Worker 	sock = ( TCPSocket* ) platform_data;
2141*48a54d36SAndroid Build Coastguard Worker 	require_action( sock, exit, ret = -1 );
2142*48a54d36SAndroid Build Coastguard Worker 	require_action( sock->fd == fd, exit, ret = -1 );
2143*48a54d36SAndroid Build Coastguard Worker 
2144*48a54d36SAndroid Build Coastguard Worker 	ret = mDNSPlatformReadTCP( sock, buf, len, &closed );
2145*48a54d36SAndroid Build Coastguard Worker 
2146*48a54d36SAndroid Build Coastguard Worker 	if ( closed )
2147*48a54d36SAndroid Build Coastguard Worker 	{
2148*48a54d36SAndroid Build Coastguard Worker 		ret = 0;
2149*48a54d36SAndroid Build Coastguard Worker 	}
2150*48a54d36SAndroid Build Coastguard Worker 
2151*48a54d36SAndroid Build Coastguard Worker exit:
2152*48a54d36SAndroid Build Coastguard Worker 
2153*48a54d36SAndroid Build Coastguard Worker 	return ret;
2154*48a54d36SAndroid Build Coastguard Worker }
2155*48a54d36SAndroid Build Coastguard Worker 
2156*48a54d36SAndroid Build Coastguard Worker 
2157*48a54d36SAndroid Build Coastguard Worker mStatus
udsSupportRemoveFDFromEventLoop(SocketRef fd,void * platform_data)2158*48a54d36SAndroid Build Coastguard Worker udsSupportRemoveFDFromEventLoop( SocketRef fd, void *platform_data)		// Note: This also CLOSES the socket
2159*48a54d36SAndroid Build Coastguard Worker {
2160*48a54d36SAndroid Build Coastguard Worker 	mStatus err = kNoErr;
2161*48a54d36SAndroid Build Coastguard Worker 
2162*48a54d36SAndroid Build Coastguard Worker 	if ( platform_data != NULL )
2163*48a54d36SAndroid Build Coastguard Worker 	{
2164*48a54d36SAndroid Build Coastguard Worker 		TCPSocket * sock;
2165*48a54d36SAndroid Build Coastguard Worker 
2166*48a54d36SAndroid Build Coastguard Worker 		dlog( kDebugLevelInfo, DEBUG_NAME "session closed\n" );
2167*48a54d36SAndroid Build Coastguard Worker 		sock = ( TCPSocket* ) platform_data;
2168*48a54d36SAndroid Build Coastguard Worker 		check( sock->fd == fd );
2169*48a54d36SAndroid Build Coastguard Worker 		mDNSPlatformTCPCloseConnection( sock );
2170*48a54d36SAndroid Build Coastguard Worker 	}
2171*48a54d36SAndroid Build Coastguard Worker 	else if ( gUDSEvent != NULL )
2172*48a54d36SAndroid Build Coastguard Worker 	{
2173*48a54d36SAndroid Build Coastguard Worker 		UnregisterWaitableEvent( &gMDNSRecord, gUDSEvent );
2174*48a54d36SAndroid Build Coastguard Worker 		WSAEventSelect( fd, gUDSEvent, 0 );
2175*48a54d36SAndroid Build Coastguard Worker 		CloseHandle( gUDSEvent );
2176*48a54d36SAndroid Build Coastguard Worker 		gUDSEvent = NULL;
2177*48a54d36SAndroid Build Coastguard Worker 	}
2178*48a54d36SAndroid Build Coastguard Worker 
2179*48a54d36SAndroid Build Coastguard Worker 	return err;
2180*48a54d36SAndroid Build Coastguard Worker }
2181*48a54d36SAndroid Build Coastguard Worker 
2182*48a54d36SAndroid Build Coastguard Worker 
RecordUpdatedNiceLabel(mDNS * const m,mDNSs32 delay)2183*48a54d36SAndroid Build Coastguard Worker mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
2184*48a54d36SAndroid Build Coastguard Worker 	{
2185*48a54d36SAndroid Build Coastguard Worker 	(void)m;
2186*48a54d36SAndroid Build Coastguard Worker 	(void)delay;
2187*48a54d36SAndroid Build Coastguard Worker 	// No-op, for now
2188*48a54d36SAndroid Build Coastguard Worker 	}
2189*48a54d36SAndroid Build Coastguard Worker 
2190*48a54d36SAndroid Build Coastguard Worker 
2191*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2192*48a54d36SAndroid Build Coastguard Worker //	SystemWakeForNetworkAccess
2193*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2194*48a54d36SAndroid Build Coastguard Worker 
2195*48a54d36SAndroid Build Coastguard Worker mDNSu8
SystemWakeForNetworkAccess(LARGE_INTEGER * timeout)2196*48a54d36SAndroid Build Coastguard Worker SystemWakeForNetworkAccess( LARGE_INTEGER * timeout )
2197*48a54d36SAndroid Build Coastguard Worker {
2198*48a54d36SAndroid Build Coastguard Worker 	HKEY					key = NULL;
2199*48a54d36SAndroid Build Coastguard Worker 	DWORD					dwSize;
2200*48a54d36SAndroid Build Coastguard Worker 	DWORD					enabled;
2201*48a54d36SAndroid Build Coastguard Worker 	mDNSu8					ok;
2202*48a54d36SAndroid Build Coastguard Worker 	SYSTEM_POWER_STATUS		powerStatus;
2203*48a54d36SAndroid Build Coastguard Worker 	time_t					startTime;
2204*48a54d36SAndroid Build Coastguard Worker 	time_t					nextWakeupTime;
2205*48a54d36SAndroid Build Coastguard Worker 	int						delta;
2206*48a54d36SAndroid Build Coastguard Worker 	DWORD					err;
2207*48a54d36SAndroid Build Coastguard Worker 
2208*48a54d36SAndroid Build Coastguard Worker 	dlog( kDebugLevelInfo, DEBUG_NAME "SystemWakeForNetworkAccess\n" );
2209*48a54d36SAndroid Build Coastguard Worker 
2210*48a54d36SAndroid Build Coastguard Worker 	// Make sure we have a timer
2211*48a54d36SAndroid Build Coastguard Worker 
2212*48a54d36SAndroid Build Coastguard Worker 	require_action( gSPSWakeupEvent != NULL, exit, ok = FALSE );
2213*48a54d36SAndroid Build Coastguard Worker 	require_action( gSPSSleepEvent != NULL, exit, ok = FALSE );
2214*48a54d36SAndroid Build Coastguard Worker 
2215*48a54d36SAndroid Build Coastguard Worker 	// Make sure the user enabled bonjour sleep proxy client
2216*48a54d36SAndroid Build Coastguard Worker 
2217*48a54d36SAndroid Build Coastguard Worker 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", &key );
2218*48a54d36SAndroid Build Coastguard Worker 	require_action( !err, exit, ok = FALSE );
2219*48a54d36SAndroid Build Coastguard Worker 	dwSize = sizeof( DWORD );
2220*48a54d36SAndroid Build Coastguard Worker 	err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
2221*48a54d36SAndroid Build Coastguard Worker 	require_action( !err, exit, ok = FALSE );
2222*48a54d36SAndroid Build Coastguard Worker 	require_action( enabled, exit, ok = FALSE );
2223*48a54d36SAndroid Build Coastguard Worker 
2224*48a54d36SAndroid Build Coastguard Worker 	// Make sure machine is on AC power
2225*48a54d36SAndroid Build Coastguard Worker 
2226*48a54d36SAndroid Build Coastguard Worker 	ok = ( mDNSu8 ) GetSystemPowerStatus( &powerStatus );
2227*48a54d36SAndroid Build Coastguard Worker 	require_action( ok, exit, ok = FALSE );
2228*48a54d36SAndroid Build Coastguard Worker 	require_action( powerStatus.ACLineStatus == AC_LINE_ONLINE, exit, ok = FALSE );
2229*48a54d36SAndroid Build Coastguard Worker 
2230*48a54d36SAndroid Build Coastguard Worker 	// Now make sure we have a network interface that does wake-on-lan
2231*48a54d36SAndroid Build Coastguard Worker 
2232*48a54d36SAndroid Build Coastguard Worker 	ok = ( mDNSu8 ) IsWOMPEnabled( &gMDNSRecord );
2233*48a54d36SAndroid Build Coastguard Worker 	require_action( ok, exit, ok = FALSE );
2234*48a54d36SAndroid Build Coastguard Worker 
2235*48a54d36SAndroid Build Coastguard Worker 	// Now make sure we have advertised services. Doesn't make sense to
2236*48a54d36SAndroid Build Coastguard Worker 	// enable sleep proxy if we have no multicast services that could
2237*48a54d36SAndroid Build Coastguard Worker 	// potentially wake us up.
2238*48a54d36SAndroid Build Coastguard Worker 
2239*48a54d36SAndroid Build Coastguard Worker 	ok = ( mDNSu8 ) mDNSCoreHaveAdvertisedMulticastServices( &gMDNSRecord );
2240*48a54d36SAndroid Build Coastguard Worker 	require_action( ok, exit, ok = FALSE );
2241*48a54d36SAndroid Build Coastguard Worker 
2242*48a54d36SAndroid Build Coastguard Worker 	// Calculate next wake up time
2243*48a54d36SAndroid Build Coastguard Worker 
2244*48a54d36SAndroid Build Coastguard Worker 	startTime		= time( NULL );					// Seconds since midnight January 1, 1970
2245*48a54d36SAndroid Build Coastguard Worker 	nextWakeupTime	= startTime + ( 120 * 60 );		// 2 hours later
2246*48a54d36SAndroid Build Coastguard Worker 
2247*48a54d36SAndroid Build Coastguard Worker 	if ( gMDNSRecord.p->nextDHCPLeaseExpires < nextWakeupTime )
2248*48a54d36SAndroid Build Coastguard Worker 	{
2249*48a54d36SAndroid Build Coastguard Worker 		nextWakeupTime = gMDNSRecord.p->nextDHCPLeaseExpires;
2250*48a54d36SAndroid Build Coastguard Worker 	}
2251*48a54d36SAndroid Build Coastguard Worker 
2252*48a54d36SAndroid Build Coastguard Worker 	// Finally calculate the next relative wakeup time
2253*48a54d36SAndroid Build Coastguard Worker 
2254*48a54d36SAndroid Build Coastguard Worker 	delta = ( int )( ( ( double )( nextWakeupTime - startTime ) ) * 0.9 );
2255*48a54d36SAndroid Build Coastguard Worker 	ReportStatus( EVENTLOG_INFORMATION_TYPE, "enabling sleep proxy client with next maintenance wake in %d seconds", delta );
2256*48a54d36SAndroid Build Coastguard Worker 
2257*48a54d36SAndroid Build Coastguard Worker 	// Convert seconds to 100 nanosecond units expected by SetWaitableTimer
2258*48a54d36SAndroid Build Coastguard Worker 
2259*48a54d36SAndroid Build Coastguard Worker 	timeout->QuadPart  = -delta;
2260*48a54d36SAndroid Build Coastguard Worker 	timeout->QuadPart *= kSecondsTo100NSUnits;
2261*48a54d36SAndroid Build Coastguard Worker 
2262*48a54d36SAndroid Build Coastguard Worker 	ok = TRUE;
2263*48a54d36SAndroid Build Coastguard Worker 
2264*48a54d36SAndroid Build Coastguard Worker exit:
2265*48a54d36SAndroid Build Coastguard Worker 
2266*48a54d36SAndroid Build Coastguard Worker 	if ( key )
2267*48a54d36SAndroid Build Coastguard Worker 	{
2268*48a54d36SAndroid Build Coastguard Worker 		RegCloseKey( key );
2269*48a54d36SAndroid Build Coastguard Worker 	}
2270*48a54d36SAndroid Build Coastguard Worker 
2271*48a54d36SAndroid Build Coastguard Worker 	return ok;
2272*48a54d36SAndroid Build Coastguard Worker }
2273*48a54d36SAndroid Build Coastguard Worker 
2274*48a54d36SAndroid Build Coastguard Worker 
2275*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2276*48a54d36SAndroid Build Coastguard Worker //	HaveRoute
2277*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2278*48a54d36SAndroid Build Coastguard Worker 
2279*48a54d36SAndroid Build Coastguard Worker static bool
HaveRoute(PMIB_IPFORWARDROW rowExtant,unsigned long addr,unsigned long metric)2280*48a54d36SAndroid Build Coastguard Worker HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric )
2281*48a54d36SAndroid Build Coastguard Worker {
2282*48a54d36SAndroid Build Coastguard Worker 	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
2283*48a54d36SAndroid Build Coastguard Worker 	DWORD				dwSize			= 0;
2284*48a54d36SAndroid Build Coastguard Worker 	BOOL				bOrder			= FALSE;
2285*48a54d36SAndroid Build Coastguard Worker 	OSStatus			err;
2286*48a54d36SAndroid Build Coastguard Worker 	bool				found			= false;
2287*48a54d36SAndroid Build Coastguard Worker 	unsigned long int	i;
2288*48a54d36SAndroid Build Coastguard Worker 
2289*48a54d36SAndroid Build Coastguard Worker 	//
2290*48a54d36SAndroid Build Coastguard Worker 	// Find out how big our buffer needs to be.
2291*48a54d36SAndroid Build Coastguard Worker 	//
2292*48a54d36SAndroid Build Coastguard Worker 	err = GetIpForwardTable(NULL, &dwSize, bOrder);
2293*48a54d36SAndroid Build Coastguard Worker 	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
2294*48a54d36SAndroid Build Coastguard Worker 
2295*48a54d36SAndroid Build Coastguard Worker 	//
2296*48a54d36SAndroid Build Coastguard Worker 	// Allocate the memory for the table
2297*48a54d36SAndroid Build Coastguard Worker 	//
2298*48a54d36SAndroid Build Coastguard Worker 	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
2299*48a54d36SAndroid Build Coastguard Worker 	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
2300*48a54d36SAndroid Build Coastguard Worker 
2301*48a54d36SAndroid Build Coastguard Worker 	//
2302*48a54d36SAndroid Build Coastguard Worker 	// Now get the table.
2303*48a54d36SAndroid Build Coastguard Worker 	//
2304*48a54d36SAndroid Build Coastguard Worker 	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
2305*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
2306*48a54d36SAndroid Build Coastguard Worker 
2307*48a54d36SAndroid Build Coastguard Worker 	//
2308*48a54d36SAndroid Build Coastguard Worker 	// Search for the row in the table we want.
2309*48a54d36SAndroid Build Coastguard Worker 	//
2310*48a54d36SAndroid Build Coastguard Worker 	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
2311*48a54d36SAndroid Build Coastguard Worker 	{
2312*48a54d36SAndroid Build Coastguard Worker 		if ( ( pIpForwardTable->table[i].dwForwardDest == addr ) && ( !metric || ( pIpForwardTable->table[i].dwForwardMetric1 == metric ) ) )
2313*48a54d36SAndroid Build Coastguard Worker 		{
2314*48a54d36SAndroid Build Coastguard Worker 			memcpy( rowExtant, &(pIpForwardTable->table[i]), sizeof(*rowExtant) );
2315*48a54d36SAndroid Build Coastguard Worker 			found = true;
2316*48a54d36SAndroid Build Coastguard Worker 			break;
2317*48a54d36SAndroid Build Coastguard Worker 		}
2318*48a54d36SAndroid Build Coastguard Worker 	}
2319*48a54d36SAndroid Build Coastguard Worker 
2320*48a54d36SAndroid Build Coastguard Worker exit:
2321*48a54d36SAndroid Build Coastguard Worker 
2322*48a54d36SAndroid Build Coastguard Worker 	if ( pIpForwardTable != NULL )
2323*48a54d36SAndroid Build Coastguard Worker 	{
2324*48a54d36SAndroid Build Coastguard Worker 		free(pIpForwardTable);
2325*48a54d36SAndroid Build Coastguard Worker 	}
2326*48a54d36SAndroid Build Coastguard Worker 
2327*48a54d36SAndroid Build Coastguard Worker 	return found;
2328*48a54d36SAndroid Build Coastguard Worker }
2329*48a54d36SAndroid Build Coastguard Worker 
2330*48a54d36SAndroid Build Coastguard Worker 
2331*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2332*48a54d36SAndroid Build Coastguard Worker //	IsValidAddress
2333*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2334*48a54d36SAndroid Build Coastguard Worker 
2335*48a54d36SAndroid Build Coastguard Worker static bool
IsValidAddress(const char * addr)2336*48a54d36SAndroid Build Coastguard Worker IsValidAddress( const char * addr )
2337*48a54d36SAndroid Build Coastguard Worker {
2338*48a54d36SAndroid Build Coastguard Worker 	return ( addr && ( strcmp( addr, "0.0.0.0" ) != 0 ) ) ? true : false;
2339*48a54d36SAndroid Build Coastguard Worker }
2340*48a54d36SAndroid Build Coastguard Worker 
2341*48a54d36SAndroid Build Coastguard Worker 
2342*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2343*48a54d36SAndroid Build Coastguard Worker //	GetAdditionalMetric
2344*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2345*48a54d36SAndroid Build Coastguard Worker 
2346*48a54d36SAndroid Build Coastguard Worker static ULONG
GetAdditionalMetric(DWORD ifIndex)2347*48a54d36SAndroid Build Coastguard Worker GetAdditionalMetric( DWORD ifIndex )
2348*48a54d36SAndroid Build Coastguard Worker {
2349*48a54d36SAndroid Build Coastguard Worker 	ULONG metric = 0;
2350*48a54d36SAndroid Build Coastguard Worker 
2351*48a54d36SAndroid Build Coastguard Worker 	if( !gIPHelperLibraryInstance )
2352*48a54d36SAndroid Build Coastguard Worker 	{
2353*48a54d36SAndroid Build Coastguard Worker 		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
2354*48a54d36SAndroid Build Coastguard Worker 
2355*48a54d36SAndroid Build Coastguard Worker 		gGetIpInterfaceEntryFunctionPtr =
2356*48a54d36SAndroid Build Coastguard Worker 				(GetIpInterfaceEntryFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetIpInterfaceEntry" );
2357*48a54d36SAndroid Build Coastguard Worker 
2358*48a54d36SAndroid Build Coastguard Worker 		if( !gGetIpInterfaceEntryFunctionPtr )
2359*48a54d36SAndroid Build Coastguard Worker 		{
2360*48a54d36SAndroid Build Coastguard Worker 			BOOL ok;
2361*48a54d36SAndroid Build Coastguard Worker 
2362*48a54d36SAndroid Build Coastguard Worker 			ok = FreeLibrary( gIPHelperLibraryInstance );
2363*48a54d36SAndroid Build Coastguard Worker 			check_translated_errno( ok, GetLastError(), kUnknownErr );
2364*48a54d36SAndroid Build Coastguard Worker 			gIPHelperLibraryInstance = NULL;
2365*48a54d36SAndroid Build Coastguard Worker 		}
2366*48a54d36SAndroid Build Coastguard Worker 	}
2367*48a54d36SAndroid Build Coastguard Worker 
2368*48a54d36SAndroid Build Coastguard Worker 	if ( gGetIpInterfaceEntryFunctionPtr )
2369*48a54d36SAndroid Build Coastguard Worker 	{
2370*48a54d36SAndroid Build Coastguard Worker 		MIB_IPINTERFACE_ROW row;
2371*48a54d36SAndroid Build Coastguard Worker 		DWORD err;
2372*48a54d36SAndroid Build Coastguard Worker 
2373*48a54d36SAndroid Build Coastguard Worker 		ZeroMemory( &row, sizeof( MIB_IPINTERFACE_ROW ) );
2374*48a54d36SAndroid Build Coastguard Worker 		row.Family = AF_INET;
2375*48a54d36SAndroid Build Coastguard Worker 		row.InterfaceIndex = ifIndex;
2376*48a54d36SAndroid Build Coastguard Worker 		err = gGetIpInterfaceEntryFunctionPtr( &row );
2377*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2378*48a54d36SAndroid Build Coastguard Worker 		metric = row.Metric + 256;
2379*48a54d36SAndroid Build Coastguard Worker 	}
2380*48a54d36SAndroid Build Coastguard Worker 
2381*48a54d36SAndroid Build Coastguard Worker exit:
2382*48a54d36SAndroid Build Coastguard Worker 
2383*48a54d36SAndroid Build Coastguard Worker 	return metric;
2384*48a54d36SAndroid Build Coastguard Worker }
2385*48a54d36SAndroid Build Coastguard Worker 
2386*48a54d36SAndroid Build Coastguard Worker 
2387*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2388*48a54d36SAndroid Build Coastguard Worker //	SetLLRoute
2389*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2390*48a54d36SAndroid Build Coastguard Worker 
2391*48a54d36SAndroid Build Coastguard Worker static OSStatus
SetLLRoute(mDNS * const inMDNS)2392*48a54d36SAndroid Build Coastguard Worker SetLLRoute( mDNS * const inMDNS )
2393*48a54d36SAndroid Build Coastguard Worker {
2394*48a54d36SAndroid Build Coastguard Worker 	OSStatus err = kNoErr;
2395*48a54d36SAndroid Build Coastguard Worker 
2396*48a54d36SAndroid Build Coastguard Worker 	DEBUG_UNUSED( inMDNS );
2397*48a54d36SAndroid Build Coastguard Worker 
2398*48a54d36SAndroid Build Coastguard Worker 	//
2399*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/4096464> Don't call SetLLRoute on loopback
2400*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/6885843> Default route on Windows 7 breaks network connectivity
2401*48a54d36SAndroid Build Coastguard Worker 	//
2402*48a54d36SAndroid Build Coastguard Worker 	// Don't mess w/ the routing table on Vista and later OSes, as
2403*48a54d36SAndroid Build Coastguard Worker 	// they have a permanent route to link-local addresses. Otherwise,
2404*48a54d36SAndroid Build Coastguard Worker 	// set a route to link local addresses (169.254.0.0)
2405*48a54d36SAndroid Build Coastguard Worker 	//
2406*48a54d36SAndroid Build Coastguard Worker 	if ( ( gOSMajorVersion < 6 ) && gServiceManageLLRouting && !gPlatformStorage.registeredLoopback4 )
2407*48a54d36SAndroid Build Coastguard Worker 	{
2408*48a54d36SAndroid Build Coastguard Worker 		DWORD				ifIndex;
2409*48a54d36SAndroid Build Coastguard Worker 		MIB_IPFORWARDROW	rowExtant;
2410*48a54d36SAndroid Build Coastguard Worker 		bool				addRoute;
2411*48a54d36SAndroid Build Coastguard Worker 		MIB_IPFORWARDROW	row;
2412*48a54d36SAndroid Build Coastguard Worker 
2413*48a54d36SAndroid Build Coastguard Worker 		ZeroMemory(&row, sizeof(row));
2414*48a54d36SAndroid Build Coastguard Worker 
2415*48a54d36SAndroid Build Coastguard Worker 		err = GetRouteDestination(&ifIndex, &row.dwForwardNextHop);
2416*48a54d36SAndroid Build Coastguard Worker 		require_noerr( err, exit );
2417*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardDest		= inet_addr(kLLNetworkAddr);
2418*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardIfIndex	= ifIndex;
2419*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMask		= inet_addr(kLLNetworkAddrMask);
2420*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardType		= 3;
2421*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardProto		= MIB_IPPROTO_NETMGMT;
2422*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardAge		= 0;
2423*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardPolicy		= 0;
2424*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMetric1	= 20 + GetAdditionalMetric( ifIndex );
2425*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMetric2	= (DWORD) - 1;
2426*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMetric3	= (DWORD) - 1;
2427*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMetric4	= (DWORD) - 1;
2428*48a54d36SAndroid Build Coastguard Worker 		row.dwForwardMetric5	= (DWORD) - 1;
2429*48a54d36SAndroid Build Coastguard Worker 
2430*48a54d36SAndroid Build Coastguard Worker 		addRoute = true;
2431*48a54d36SAndroid Build Coastguard Worker 
2432*48a54d36SAndroid Build Coastguard Worker 		//
2433*48a54d36SAndroid Build Coastguard Worker 		// check to make sure we don't already have a route
2434*48a54d36SAndroid Build Coastguard Worker 		//
2435*48a54d36SAndroid Build Coastguard Worker 		if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ), 0 ) )
2436*48a54d36SAndroid Build Coastguard Worker 		{
2437*48a54d36SAndroid Build Coastguard Worker 			//
2438*48a54d36SAndroid Build Coastguard Worker 			// set the age to 0 so that we can do a memcmp.
2439*48a54d36SAndroid Build Coastguard Worker 			//
2440*48a54d36SAndroid Build Coastguard Worker 			rowExtant.dwForwardAge = 0;
2441*48a54d36SAndroid Build Coastguard Worker 
2442*48a54d36SAndroid Build Coastguard Worker 			//
2443*48a54d36SAndroid Build Coastguard Worker 			// check to see if this route is the same as our route
2444*48a54d36SAndroid Build Coastguard Worker 			//
2445*48a54d36SAndroid Build Coastguard Worker 			if (memcmp(&row, &rowExtant, sizeof(row)) != 0)
2446*48a54d36SAndroid Build Coastguard Worker 			{
2447*48a54d36SAndroid Build Coastguard Worker 				//
2448*48a54d36SAndroid Build Coastguard Worker 				// if it isn't then delete this entry
2449*48a54d36SAndroid Build Coastguard Worker 				//
2450*48a54d36SAndroid Build Coastguard Worker 				DeleteIpForwardEntry(&rowExtant);
2451*48a54d36SAndroid Build Coastguard Worker 			}
2452*48a54d36SAndroid Build Coastguard Worker 			else
2453*48a54d36SAndroid Build Coastguard Worker 			{
2454*48a54d36SAndroid Build Coastguard Worker 				//
2455*48a54d36SAndroid Build Coastguard Worker 				// else it is, so we don't want to create another route
2456*48a54d36SAndroid Build Coastguard Worker 				//
2457*48a54d36SAndroid Build Coastguard Worker 				addRoute = false;
2458*48a54d36SAndroid Build Coastguard Worker 			}
2459*48a54d36SAndroid Build Coastguard Worker 		}
2460*48a54d36SAndroid Build Coastguard Worker 
2461*48a54d36SAndroid Build Coastguard Worker 		if (addRoute && row.dwForwardNextHop)
2462*48a54d36SAndroid Build Coastguard Worker 		{
2463*48a54d36SAndroid Build Coastguard Worker 			err = CreateIpForwardEntry(&row);
2464*48a54d36SAndroid Build Coastguard Worker 			check_noerr( err );
2465*48a54d36SAndroid Build Coastguard Worker 		}
2466*48a54d36SAndroid Build Coastguard Worker 	}
2467*48a54d36SAndroid Build Coastguard Worker 
2468*48a54d36SAndroid Build Coastguard Worker exit:
2469*48a54d36SAndroid Build Coastguard Worker 
2470*48a54d36SAndroid Build Coastguard Worker 	return ( err );
2471*48a54d36SAndroid Build Coastguard Worker }
2472*48a54d36SAndroid Build Coastguard Worker 
2473*48a54d36SAndroid Build Coastguard Worker 
2474*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2475*48a54d36SAndroid Build Coastguard Worker //	GetRouteDestination
2476*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
2477*48a54d36SAndroid Build Coastguard Worker 
2478*48a54d36SAndroid Build Coastguard Worker static OSStatus
GetRouteDestination(DWORD * ifIndex,DWORD * address)2479*48a54d36SAndroid Build Coastguard Worker GetRouteDestination(DWORD * ifIndex, DWORD * address)
2480*48a54d36SAndroid Build Coastguard Worker {
2481*48a54d36SAndroid Build Coastguard Worker 	struct in_addr		ia;
2482*48a54d36SAndroid Build Coastguard Worker 	IP_ADAPTER_INFO	*	pAdapterInfo	=	NULL;
2483*48a54d36SAndroid Build Coastguard Worker 	IP_ADAPTER_INFO	*	pAdapter		=	NULL;
2484*48a54d36SAndroid Build Coastguard Worker 	ULONG				bufLen;
2485*48a54d36SAndroid Build Coastguard Worker 	mDNSBool			done			=	mDNSfalse;
2486*48a54d36SAndroid Build Coastguard Worker 	OSStatus			err;
2487*48a54d36SAndroid Build Coastguard Worker 
2488*48a54d36SAndroid Build Coastguard Worker 	//
2489*48a54d36SAndroid Build Coastguard Worker 	// GetBestInterface will fail if there is no default gateway
2490*48a54d36SAndroid Build Coastguard Worker 	// configured.  If that happens, we will just take the first
2491*48a54d36SAndroid Build Coastguard Worker 	// interface in the list. MSDN support says there is no surefire
2492*48a54d36SAndroid Build Coastguard Worker 	// way to manually determine what the best interface might
2493*48a54d36SAndroid Build Coastguard Worker 	// be for a particular network address.
2494*48a54d36SAndroid Build Coastguard Worker 	//
2495*48a54d36SAndroid Build Coastguard Worker 	ia.s_addr	=	inet_addr(kLLNetworkAddr);
2496*48a54d36SAndroid Build Coastguard Worker 	err			=	GetBestInterface(*(IPAddr*) &ia, ifIndex);
2497*48a54d36SAndroid Build Coastguard Worker 
2498*48a54d36SAndroid Build Coastguard Worker 	if (err)
2499*48a54d36SAndroid Build Coastguard Worker 	{
2500*48a54d36SAndroid Build Coastguard Worker 		*ifIndex = 0;
2501*48a54d36SAndroid Build Coastguard Worker 	}
2502*48a54d36SAndroid Build Coastguard Worker 
2503*48a54d36SAndroid Build Coastguard Worker 	//
2504*48a54d36SAndroid Build Coastguard Worker 	// Make an initial call to GetAdaptersInfo to get
2505*48a54d36SAndroid Build Coastguard Worker 	// the necessary size into the bufLen variable
2506*48a54d36SAndroid Build Coastguard Worker 	//
2507*48a54d36SAndroid Build Coastguard Worker 	err = GetAdaptersInfo( NULL, &bufLen);
2508*48a54d36SAndroid Build Coastguard Worker 	require_action( err == ERROR_BUFFER_OVERFLOW, exit, err = kUnknownErr );
2509*48a54d36SAndroid Build Coastguard Worker 
2510*48a54d36SAndroid Build Coastguard Worker 	pAdapterInfo = (IP_ADAPTER_INFO*) malloc( bufLen );
2511*48a54d36SAndroid Build Coastguard Worker 	require_action( pAdapterInfo, exit, err = kNoMemoryErr );
2512*48a54d36SAndroid Build Coastguard Worker 
2513*48a54d36SAndroid Build Coastguard Worker 	err = GetAdaptersInfo( pAdapterInfo, &bufLen);
2514*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
2515*48a54d36SAndroid Build Coastguard Worker 
2516*48a54d36SAndroid Build Coastguard Worker 	pAdapter	=	pAdapterInfo;
2517*48a54d36SAndroid Build Coastguard Worker 	err			=	kUnknownErr;
2518*48a54d36SAndroid Build Coastguard Worker 
2519*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/3718122>
2520*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/5652098>
2521*48a54d36SAndroid Build Coastguard Worker 	//
2522*48a54d36SAndroid Build Coastguard Worker 	// Look for the Nortel VPN virtual interface, along with Juniper virtual interface.
2523*48a54d36SAndroid Build Coastguard Worker 	//
2524*48a54d36SAndroid Build Coastguard Worker 	// If these interfaces are active (i.e., has a non-zero IP Address),
2525*48a54d36SAndroid Build Coastguard Worker 	// then we want to disable routing table modifications.
2526*48a54d36SAndroid Build Coastguard Worker 
2527*48a54d36SAndroid Build Coastguard Worker 	while (pAdapter)
2528*48a54d36SAndroid Build Coastguard Worker 	{
2529*48a54d36SAndroid Build Coastguard Worker 		if ( ( IsNortelVPN( pAdapter ) || IsJuniperVPN( pAdapter ) || IsCiscoVPN( pAdapter ) ) &&
2530*48a54d36SAndroid Build Coastguard Worker 			 ( inet_addr( pAdapter->IpAddressList.IpAddress.String ) != 0 ) )
2531*48a54d36SAndroid Build Coastguard Worker 		{
2532*48a54d36SAndroid Build Coastguard Worker 			dlog( kDebugLevelTrace, DEBUG_NAME "disabling routing table management due to VPN incompatibility" );
2533*48a54d36SAndroid Build Coastguard Worker 			goto exit;
2534*48a54d36SAndroid Build Coastguard Worker 		}
2535*48a54d36SAndroid Build Coastguard Worker 
2536*48a54d36SAndroid Build Coastguard Worker 		pAdapter = pAdapter->Next;
2537*48a54d36SAndroid Build Coastguard Worker 	}
2538*48a54d36SAndroid Build Coastguard Worker 
2539*48a54d36SAndroid Build Coastguard Worker 	while ( !done )
2540*48a54d36SAndroid Build Coastguard Worker 	{
2541*48a54d36SAndroid Build Coastguard Worker 		pAdapter	=	pAdapterInfo;
2542*48a54d36SAndroid Build Coastguard Worker 		err			=	kUnknownErr;
2543*48a54d36SAndroid Build Coastguard Worker 
2544*48a54d36SAndroid Build Coastguard Worker 		while (pAdapter)
2545*48a54d36SAndroid Build Coastguard Worker 		{
2546*48a54d36SAndroid Build Coastguard Worker 			// If we don't have an interface selected, choose the first one that is of type ethernet and
2547*48a54d36SAndroid Build Coastguard Worker 			// has a valid IP Address
2548*48a54d36SAndroid Build Coastguard Worker 
2549*48a54d36SAndroid Build Coastguard Worker 			if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && ( IsValidAddress( pAdapter->IpAddressList.IpAddress.String ) ) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex))))
2550*48a54d36SAndroid Build Coastguard Worker 			{
2551*48a54d36SAndroid Build Coastguard Worker 				*address =	inet_addr( pAdapter->IpAddressList.IpAddress.String );
2552*48a54d36SAndroid Build Coastguard Worker 				*ifIndex =  pAdapter->Index;
2553*48a54d36SAndroid Build Coastguard Worker 				err		 =	kNoErr;
2554*48a54d36SAndroid Build Coastguard Worker 				break;
2555*48a54d36SAndroid Build Coastguard Worker 			}
2556*48a54d36SAndroid Build Coastguard Worker 
2557*48a54d36SAndroid Build Coastguard Worker 			pAdapter = pAdapter->Next;
2558*48a54d36SAndroid Build Coastguard Worker 		}
2559*48a54d36SAndroid Build Coastguard Worker 
2560*48a54d36SAndroid Build Coastguard Worker 		// If we found the right interface, or we weren't trying to find a specific interface then we're done
2561*48a54d36SAndroid Build Coastguard Worker 
2562*48a54d36SAndroid Build Coastguard Worker 		if ( !err || !( *ifIndex) )
2563*48a54d36SAndroid Build Coastguard Worker 		{
2564*48a54d36SAndroid Build Coastguard Worker 			done = mDNStrue;
2565*48a54d36SAndroid Build Coastguard Worker 		}
2566*48a54d36SAndroid Build Coastguard Worker 
2567*48a54d36SAndroid Build Coastguard Worker 		// Otherwise, try again by wildcarding the interface
2568*48a54d36SAndroid Build Coastguard Worker 
2569*48a54d36SAndroid Build Coastguard Worker 		else
2570*48a54d36SAndroid Build Coastguard Worker 		{
2571*48a54d36SAndroid Build Coastguard Worker 			*ifIndex = 0;
2572*48a54d36SAndroid Build Coastguard Worker 		}
2573*48a54d36SAndroid Build Coastguard Worker 	}
2574*48a54d36SAndroid Build Coastguard Worker 
2575*48a54d36SAndroid Build Coastguard Worker exit:
2576*48a54d36SAndroid Build Coastguard Worker 
2577*48a54d36SAndroid Build Coastguard Worker 	if ( pAdapterInfo != NULL )
2578*48a54d36SAndroid Build Coastguard Worker 	{
2579*48a54d36SAndroid Build Coastguard Worker 		free( pAdapterInfo );
2580*48a54d36SAndroid Build Coastguard Worker 	}
2581*48a54d36SAndroid Build Coastguard Worker 
2582*48a54d36SAndroid Build Coastguard Worker 	return( err );
2583*48a54d36SAndroid Build Coastguard Worker }
2584*48a54d36SAndroid Build Coastguard Worker 
2585*48a54d36SAndroid Build Coastguard Worker 
2586*48a54d36SAndroid Build Coastguard Worker static bool
IsNortelVPN(IP_ADAPTER_INFO * pAdapter)2587*48a54d36SAndroid Build Coastguard Worker IsNortelVPN( IP_ADAPTER_INFO * pAdapter )
2588*48a54d36SAndroid Build Coastguard Worker {
2589*48a54d36SAndroid Build Coastguard Worker 	return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
2590*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->AddressLength == 6) &&
2591*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[0] == 0x44) &&
2592*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[1] == 0x45) &&
2593*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[2] == 0x53) &&
2594*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[3] == 0x54) &&
2595*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[4] == 0x42) &&
2596*48a54d36SAndroid Build Coastguard Worker 			(pAdapter->Address[5] == 0x00)) ? true : false;
2597*48a54d36SAndroid Build Coastguard Worker }
2598*48a54d36SAndroid Build Coastguard Worker 
2599*48a54d36SAndroid Build Coastguard Worker 
2600*48a54d36SAndroid Build Coastguard Worker static bool
IsJuniperVPN(IP_ADAPTER_INFO * pAdapter)2601*48a54d36SAndroid Build Coastguard Worker IsJuniperVPN( IP_ADAPTER_INFO * pAdapter )
2602*48a54d36SAndroid Build Coastguard Worker {
2603*48a54d36SAndroid Build Coastguard Worker 	return ( strnistr( pAdapter->Description, "Juniper", sizeof( pAdapter->Description  ) ) != NULL ) ? true : false;
2604*48a54d36SAndroid Build Coastguard Worker }
2605*48a54d36SAndroid Build Coastguard Worker 
2606*48a54d36SAndroid Build Coastguard Worker 
2607*48a54d36SAndroid Build Coastguard Worker static bool
IsCiscoVPN(IP_ADAPTER_INFO * pAdapter)2608*48a54d36SAndroid Build Coastguard Worker IsCiscoVPN( IP_ADAPTER_INFO * pAdapter )
2609*48a54d36SAndroid Build Coastguard Worker {
2610*48a54d36SAndroid Build Coastguard Worker 	return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
2611*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->AddressLength == 6) &&
2612*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[0] == 0x00) &&
2613*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[1] == 0x05) &&
2614*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[2] == 0x9a) &&
2615*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[3] == 0x3c) &&
2616*48a54d36SAndroid Build Coastguard Worker 		    (pAdapter->Address[4] == 0x7a) &&
2617*48a54d36SAndroid Build Coastguard Worker 			(pAdapter->Address[5] == 0x00)) ? true : false;
2618*48a54d36SAndroid Build Coastguard Worker }
2619*48a54d36SAndroid Build Coastguard Worker 
2620*48a54d36SAndroid Build Coastguard Worker 
2621*48a54d36SAndroid Build Coastguard Worker static const char *
strnistr(const char * string,const char * subString,size_t max)2622*48a54d36SAndroid Build Coastguard Worker strnistr( const char * string, const char * subString, size_t max )
2623*48a54d36SAndroid Build Coastguard Worker {
2624*48a54d36SAndroid Build Coastguard Worker 	size_t       subStringLen;
2625*48a54d36SAndroid Build Coastguard Worker 	size_t       offset;
2626*48a54d36SAndroid Build Coastguard Worker 	size_t       maxOffset;
2627*48a54d36SAndroid Build Coastguard Worker 	size_t       stringLen;
2628*48a54d36SAndroid Build Coastguard Worker 	const char * pPos;
2629*48a54d36SAndroid Build Coastguard Worker 
2630*48a54d36SAndroid Build Coastguard Worker 	if ( ( string == NULL ) || ( subString == NULL ) )
2631*48a54d36SAndroid Build Coastguard Worker 	{
2632*48a54d36SAndroid Build Coastguard Worker 		return string;
2633*48a54d36SAndroid Build Coastguard Worker 	}
2634*48a54d36SAndroid Build Coastguard Worker 
2635*48a54d36SAndroid Build Coastguard Worker 	stringLen = ( max > strlen( string ) ) ? strlen( string ) : max;
2636*48a54d36SAndroid Build Coastguard Worker 
2637*48a54d36SAndroid Build Coastguard Worker 	if ( stringLen == 0 )
2638*48a54d36SAndroid Build Coastguard Worker 	{
2639*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2640*48a54d36SAndroid Build Coastguard Worker 	}
2641*48a54d36SAndroid Build Coastguard Worker 
2642*48a54d36SAndroid Build Coastguard Worker 	subStringLen = strlen( subString );
2643*48a54d36SAndroid Build Coastguard Worker 
2644*48a54d36SAndroid Build Coastguard Worker 	if ( subStringLen == 0 )
2645*48a54d36SAndroid Build Coastguard Worker 	{
2646*48a54d36SAndroid Build Coastguard Worker 		return string;
2647*48a54d36SAndroid Build Coastguard Worker 	}
2648*48a54d36SAndroid Build Coastguard Worker 
2649*48a54d36SAndroid Build Coastguard Worker 	if ( subStringLen > stringLen )
2650*48a54d36SAndroid Build Coastguard Worker 	{
2651*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2652*48a54d36SAndroid Build Coastguard Worker 	}
2653*48a54d36SAndroid Build Coastguard Worker 
2654*48a54d36SAndroid Build Coastguard Worker 	maxOffset = stringLen - subStringLen;
2655*48a54d36SAndroid Build Coastguard Worker 	pPos      = string;
2656*48a54d36SAndroid Build Coastguard Worker 
2657*48a54d36SAndroid Build Coastguard Worker 	for ( offset = 0; offset <= maxOffset; offset++ )
2658*48a54d36SAndroid Build Coastguard Worker 	{
2659*48a54d36SAndroid Build Coastguard Worker 		if ( _strnicmp( pPos, subString, subStringLen ) == 0 )
2660*48a54d36SAndroid Build Coastguard Worker 		{
2661*48a54d36SAndroid Build Coastguard Worker 			return pPos;
2662*48a54d36SAndroid Build Coastguard Worker 		}
2663*48a54d36SAndroid Build Coastguard Worker 
2664*48a54d36SAndroid Build Coastguard Worker 		pPos++;
2665*48a54d36SAndroid Build Coastguard Worker 	}
2666*48a54d36SAndroid Build Coastguard Worker 
2667*48a54d36SAndroid Build Coastguard Worker 	return NULL;
2668*48a54d36SAndroid Build Coastguard Worker }
2669*48a54d36SAndroid Build Coastguard Worker 
2670