• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include	<stdio.h>
19 #include	<stdlib.h>
20 
21 #include	"CommonServices.h"
22 #include	"DebugServices.h"
23 
24 #include	<guiddef.h>
25 #include	<ws2spi.h>
26 
27 //===========================================================================================================================
28 //	Prototypes
29 //===========================================================================================================================
30 
31 int  					main( int argc, char *argv[] );
32 DEBUG_LOCAL void		Usage( void );
33 DEBUG_LOCAL int			ProcessArgs( int argc, char *argv[] );
34 DEBUG_LOCAL OSStatus	InstallNSP( const char *inName, const char *inGUID, const char *inPath );
35 DEBUG_LOCAL OSStatus	RemoveNSP( const char *inGUID );
36 DEBUG_LOCAL OSStatus	EnableNSP( const char *inGUID, BOOL inEnable );
37 DEBUG_LOCAL OSStatus	ListNameSpaces( void );
38 DEBUG_LOCAL OSStatus	ReorderNameSpaces( void );
39 
40 DEBUG_LOCAL WCHAR *		CharToWCharString( const char *inCharString, WCHAR *outWCharString );
41 DEBUG_LOCAL char *		GUIDtoString( const GUID *inGUID, char *outString );
42 DEBUG_LOCAL OSStatus	StringToGUID( const char *inCharString, GUID *outGUID );
43 
44 DEBUG_LOCAL BOOL gToolQuietMode = FALSE;
45 
46 //===========================================================================================================================
47 //	main
48 //===========================================================================================================================
49 
main(int argc,char * argv[])50 int main( int argc, char *argv[] )
51 {
52 	OSStatus		err;
53 
54 	debug_initialize( kDebugOutputTypeMetaConsole );
55 	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
56 
57 	err = ProcessArgs( argc, argv );
58 	return( (int) err );
59 }
60 
61 //===========================================================================================================================
62 //	Usage
63 //===========================================================================================================================
64 
Usage(void)65 DEBUG_LOCAL void	Usage( void )
66 {
67 	fprintf( stderr, "\n" );
68 	fprintf( stderr, "NSP Tool 1.0d1\n" );
69 	fprintf( stderr, "  Name Space Provider Tool\n" );
70 	fprintf( stderr, "\n" );
71 
72 	fprintf( stderr, "  -install <name> <guid> <path>   - Installs a Name Space Provider\n" );
73 	fprintf( stderr, "\n" );
74 	fprintf( stderr, "      <name> Name of the NSP\n" );
75 	fprintf( stderr, "      <guid> GUID of the NSP\n" );
76 	fprintf( stderr, "      <path> Path to the NSP file\n" );
77 	fprintf( stderr, "\n" );
78 
79 	fprintf( stderr, "  -remove <guid>                  - Removes a Name Space Provider\n" );
80 	fprintf( stderr, "\n" );
81 	fprintf( stderr, "      <guid> GUID of the NSP\n" );
82 	fprintf( stderr, "\n" );
83 
84 	fprintf( stderr, "  -enable/-disable <guid>         - Enables or Disables a Name Space Provider\n" );
85 	fprintf( stderr, "\n" );
86 	fprintf( stderr, "      <guid> GUID of the NSP\n" );
87 	fprintf( stderr, "\n" );
88 
89 	fprintf( stderr, "  -list                           - Lists Name Space Providers\n" );
90 	fprintf( stderr, "  -reorder                        - Reorders Name Space Providers\n" );
91 	fprintf( stderr, "  -q                              - Enable quiet mode\n" );
92 	fprintf( stderr, "  -h[elp]                         - Help\n" );
93 	fprintf( stderr, "\n" );
94 }
95 
96 //===========================================================================================================================
97 //	ProcessArgs
98 //===========================================================================================================================
99 
ProcessArgs(int argc,char * argv[])100 DEBUG_LOCAL int ProcessArgs( int argc, char* argv[] )
101 {
102 	OSStatus			err;
103 	int					i;
104 	const char *		name;
105 	const char *		guid;
106 	const char *		path;
107 
108 	if( argc <= 1 )
109 	{
110 		Usage();
111 		err = 0;
112 		goto exit;
113 	}
114 	for( i = 1; i < argc; ++i )
115 	{
116 		if( strcmp( argv[ i ], "-install" ) == 0 )
117 		{
118 			// Install
119 
120 			if( argc <= ( i + 3 ) )
121 			{
122 				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
123 				Usage();
124 				err = kParamErr;
125 				goto exit;
126 			}
127 			name = argv[ ++i ];
128 			guid = argv[ ++i ];
129 			path = argv[ ++i ];
130 
131 			if( *name == '\0' )
132 			{
133 				name = "DotLocalNSP";
134 			}
135 			if( *guid == '\0' )
136 			{
137 				guid = "B600E6E9-553B-4a19-8696-335E5C896153";
138 			}
139 
140 			err = InstallNSP( name, guid, path );
141 			require_noerr( err, exit );
142 		}
143 		else if( strcmp( argv[ i ], "-remove" ) == 0 )
144 		{
145 			// Remove
146 
147 			if( argc <= ( i + 1 ) )
148 			{
149 				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
150 				Usage();
151 				err = kParamErr;
152 				goto exit;
153 			}
154 			guid = argv[ ++i ];
155 			if( *guid == '\0' )
156 			{
157 				guid = "B600E6E9-553B-4a19-8696-335E5C896153";
158 			}
159 
160 			err = RemoveNSP( guid );
161 			require_noerr( err, exit );
162 		}
163 		else if( ( strcmp( argv[ i ], "-enable" )  == 0 ) ||
164 				 ( strcmp( argv[ i ], "-disable" ) == 0 ) )
165 		{
166 			BOOL		enable;
167 
168 			// Enable/Disable
169 
170 			enable = ( strcmp( argv[ i ], "-enable" ) == 0 );
171 			if( argc <= ( i + 1 ) )
172 			{
173 				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
174 				Usage();
175 				err = kParamErr;
176 				goto exit;
177 			}
178 			guid = argv[ ++i ];
179 
180 			err = EnableNSP( guid, enable );
181 			require_noerr( err, exit );
182 		}
183 		else if( strcmp( argv[ i ], "-list" ) == 0 )
184 		{
185 			// List
186 
187 			err = ListNameSpaces();
188 			require_noerr( err, exit );
189 		}
190 		else if( strcmp( argv[ i ], "-reorder" ) == 0 )
191 		{
192 			// Reorder
193 
194 			err = ReorderNameSpaces();
195 			require_noerr( err, exit );
196 		}
197 		else if( strcmp( argv[ i ], "-q" ) == 0 )
198 		{
199 			gToolQuietMode = TRUE;
200 		}
201 		else if( ( strcmp( argv[ i ], "-help" ) == 0 ) ||
202 				 ( strcmp( argv[ i ], "-h" ) == 0 ) )
203 		{
204 			// Help
205 
206 			Usage();
207 			err = 0;
208 			goto exit;
209 		}
210 		else
211 		{
212 			fprintf( stderr, "\n### ERROR: unknown argment: \"%s\"\n\n", argv[ i ] );
213 			Usage();
214 			err = kParamErr;
215 			goto exit;
216 		}
217 	}
218 	err = kNoErr;
219 
220 exit:
221 	return( err );
222 }
223 
224 #if 0
225 #pragma mark -
226 #endif
227 
228 //===========================================================================================================================
229 //	InstallNSP
230 //===========================================================================================================================
231 
InstallNSP(const char * inName,const char * inGUID,const char * inPath)232 OSStatus	InstallNSP( const char *inName, const char *inGUID, const char *inPath )
233 {
234 	OSStatus		err;
235 	size_t			size;
236 	WSADATA			wsd;
237 	WCHAR			name[ 256 ];
238 	GUID			guid;
239 	WCHAR			path[ MAX_PATH ];
240 
241 	require_action( inName && ( *inName != '\0' ), exit, err = kParamErr );
242 	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
243 	require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr );
244 
245 	size = strlen( inName );
246 	require_action( size < sizeof_array( name ), exit, err = kSizeErr );
247 	CharToWCharString( inName, name );
248 
249 	err = StringToGUID( inGUID, &guid );
250 	require_noerr( err, exit );
251 
252 	size = strlen( inPath );
253 	require_action( size < sizeof_array( path ), exit, err = kSizeErr );
254 	CharToWCharString( inPath, path );
255 
256 	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
257 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
258 	require_noerr( err, exit );
259 
260 	err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid );
261 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
262 	WSACleanup();
263 	require_noerr( err, exit );
264 
265 	if (!gToolQuietMode)
266 	{
267 		fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath );
268 	}
269 
270 exit:
271 	if( err != kNoErr )
272 	{
273 		fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath );
274 	}
275 	return( err );
276 }
277 
278 //===========================================================================================================================
279 //	RemoveNSP
280 //===========================================================================================================================
281 
RemoveNSP(const char * inGUID)282 DEBUG_LOCAL OSStatus	RemoveNSP( const char *inGUID )
283 {
284 	OSStatus		err;
285 	WSADATA			wsd;
286 	GUID			guid;
287 
288 	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
289 
290 	err = StringToGUID( inGUID, &guid );
291 	require_noerr( err, exit );
292 
293 	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
294 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
295 	require_noerr( err, exit );
296 
297 	err = WSCUnInstallNameSpace( &guid );
298 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
299 	WSACleanup();
300 	require_noerr( err, exit );
301 
302 	if (!gToolQuietMode)
303 	{
304 		fprintf( stderr, "Removed NSP %s\n", inGUID );
305 	}
306 
307 exit:
308 	if( err != kNoErr )
309 	{
310 		fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
311 	}
312 	return( err );
313 }
314 
315 //===========================================================================================================================
316 //	EnableNSP
317 //===========================================================================================================================
318 
EnableNSP(const char * inGUID,BOOL inEnable)319 DEBUG_LOCAL OSStatus	EnableNSP( const char *inGUID, BOOL inEnable )
320 {
321 	OSStatus		err;
322 	WSADATA			wsd;
323 	GUID			guid;
324 
325 	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
326 
327 	err = StringToGUID( inGUID, &guid );
328 	require_noerr( err, exit );
329 
330 	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
331 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
332 	require_noerr( err, exit );
333 
334 	err = WSCEnableNSProvider( &guid, inEnable );
335 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
336 	WSACleanup();
337 	require_noerr( err, exit );
338 
339 	if (!gToolQuietMode)
340 	{
341 		fprintf( stderr, "Removed NSP %s\n", inGUID );
342 	}
343 
344 exit:
345 	if( err != kNoErr )
346 	{
347 		fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
348 	}
349 	return( err );
350 }
351 
352 //===========================================================================================================================
353 //	ListNameSpaces
354 //===========================================================================================================================
355 
ListNameSpaces(void)356 DEBUG_LOCAL OSStatus	ListNameSpaces( void )
357 {
358 	OSStatus				err;
359 	WSADATA					wsd;
360 	bool					started;
361 	int						n;
362 	int						i;
363 	DWORD					size;
364 	WSANAMESPACE_INFO *		array;
365 	char					s[ 256 ];
366 
367 	array 	= NULL;
368 	started	= false;
369 
370 	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
371 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
372 	require_noerr( err, exit );
373 	started = true;
374 
375 	// Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
376 
377 	size = 0;
378 	n = WSAEnumNameSpaceProviders( &size, NULL );
379 	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
380 	require_action( err == WSAEFAULT, exit, err = kUnknownErr );
381 
382 	array = (WSANAMESPACE_INFO *) malloc( size );
383 	require_action( array, exit, err = kNoMemoryErr );
384 
385 	n = WSAEnumNameSpaceProviders( &size, array );
386 	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
387 	require_noerr( err, exit );
388 
389 	fprintf( stdout, "\n" );
390 	for( i = 0; i < n; ++i )
391 	{
392 		fprintf( stdout, "Name Space %d\n", i + 1 );
393 		fprintf( stdout, "    NSProviderId:   %s\n", GUIDtoString( &array[ i ].NSProviderId, s ) );
394 		fprintf( stdout, "    dwNameSpace:    %d\n", array[ i ].dwNameSpace );
395 		fprintf( stdout, "    fActive:        %s\n", array[ i ].fActive ? "YES" : "NO" );
396 		fprintf( stdout, "    dwVersion:      %d\n", array[ i ].dwVersion );
397 		fprintf( stdout, "    lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier );
398 		fprintf( stdout, "\n" );
399 	}
400 	err = kNoErr;
401 
402 exit:
403 	if( array )
404 	{
405 		free( array );
406 	}
407 	if( started )
408 	{
409 		WSACleanup();
410 	}
411 	if( err != kNoErr )
412 	{
413 		fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err );
414 	}
415 	return( err );
416 }
417 
418 //===========================================================================================================================
419 //	ReorderNameSpaces
420 //===========================================================================================================================
421 
ReorderNameSpaces(void)422 DEBUG_LOCAL OSStatus	ReorderNameSpaces( void )
423 {
424 	OSStatus				err;
425 	WSADATA					wsd;
426 	bool					started;
427 	int						n;
428 	int						i;
429 	DWORD					size;
430 	WSANAMESPACE_INFO *		array;
431 	WCHAR					name[ 256 ];
432 	WCHAR					path[ MAX_PATH ];
433 
434 	array 	= NULL;
435 	started	= false;
436 
437 	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
438 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
439 	require_noerr( err, exit );
440 	started = true;
441 
442 	// Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
443 
444 	size = 0;
445 	n = WSAEnumNameSpaceProviders( &size, NULL );
446 	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
447 	require_action( err == WSAEFAULT, exit, err = kUnknownErr );
448 
449 	array = (WSANAMESPACE_INFO *) malloc( size );
450 	require_action( array, exit, err = kNoMemoryErr );
451 
452 	n = WSAEnumNameSpaceProviders( &size, array );
453 	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
454 	require_noerr( err, exit );
455 
456 	// Find the "Tcpip" NSP.
457 
458 	for( i = 0; i < n; ++i )
459 	{
460 		if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 )
461 		{
462 			break;
463 		}
464 	}
465 	require_action( i < n, exit, err = kNotFoundErr );
466 
467 	// Uninstall it then re-install it to move it to the end.
468 
469 	size = (DWORD) strlen( array[ i ].lpszIdentifier );
470 	require_action( size < sizeof_array( name ), exit, err = kSizeErr );
471 	CharToWCharString( array[ i ].lpszIdentifier, name );
472 
473 	size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" );
474 	require_action( size < sizeof_array( path ), exit, err = kSizeErr );
475 	CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path );
476 
477 	err = WSCUnInstallNameSpace( &array[ i ].NSProviderId );
478 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
479 	require_noerr( err, exit );
480 
481 	err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId );
482 	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
483 	require_noerr( err, exit );
484 
485 	// Success!
486 
487 	fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" );
488 	err = kNoErr;
489 
490 exit:
491 	if( array )
492 	{
493 		free( array );
494 	}
495 	if( started )
496 	{
497 		WSACleanup();
498 	}
499 	if( err != kNoErr )
500 	{
501 		fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err );
502 	}
503 	return( err );
504 }
505 
506 #if 0
507 #pragma mark -
508 #endif
509 
510 //===========================================================================================================================
511 //	CharToWCharString
512 //===========================================================================================================================
513 
CharToWCharString(const char * inCharString,WCHAR * outWCharString)514 DEBUG_LOCAL WCHAR *	CharToWCharString( const char *inCharString, WCHAR *outWCharString )
515 {
516 	const char *		src;
517 	WCHAR *				dst;
518 	char				c;
519 
520 	check( inCharString );
521 	check( outWCharString );
522 
523 	src = inCharString;
524 	dst = outWCharString;
525 	do
526 	{
527 		c = *src++;
528 		*dst++ = (WCHAR) c;
529 
530 	}	while( c != '\0' );
531 
532 	return( outWCharString );
533 }
534 
535 //===========================================================================================================================
536 //	GUIDtoString
537 //===========================================================================================================================
538 
GUIDtoString(const GUID * inGUID,char * outString)539 DEBUG_LOCAL char *	GUIDtoString( const GUID *inGUID, char *outString )
540 {
541 	check( inGUID );
542 	check( outString );
543 
544 	sprintf( outString, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
545 		inGUID->Data1, inGUID->Data2, inGUID->Data3,
546 		inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ],
547 		inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] );
548 	return( outString );
549 }
550 
551 //===========================================================================================================================
552 //	StringToGUID
553 //===========================================================================================================================
554 
StringToGUID(const char * inCharString,GUID * outGUID)555 DEBUG_LOCAL OSStatus	StringToGUID( const char *inCharString, GUID *outGUID )
556 {
557 	OSStatus			err;
558 	int					n;
559 	unsigned int		v[ 8 ];
560 
561 	check( inCharString );
562 	check( outGUID );
563 
564 	n = sscanf( inCharString, "%lX-%hX-%hX-%02X%02X-%02X%02X%02X%02X%02X%02X",
565 		&outGUID->Data1, &outGUID->Data2, &outGUID->Data3,
566 		&v[ 0 ], &v[ 1 ], &v[ 2 ], &v[ 3 ], &v[ 4 ], &v[ 5 ], &v[ 6 ], &v[ 7 ] );
567 	require_action( n == 11, exit, err = kFormatErr );
568 
569 	outGUID->Data4[ 0 ] = (unsigned char) v[ 0 ];
570 	outGUID->Data4[ 1 ] = (unsigned char) v[ 1 ];
571 	outGUID->Data4[ 2 ] = (unsigned char) v[ 2 ];
572 	outGUID->Data4[ 3 ] = (unsigned char) v[ 3 ];
573 	outGUID->Data4[ 4 ] = (unsigned char) v[ 4 ];
574 	outGUID->Data4[ 5 ] = (unsigned char) v[ 5 ];
575 	outGUID->Data4[ 6 ] = (unsigned char) v[ 6 ];
576 	outGUID->Data4[ 7 ] = (unsigned char) v[ 7 ];
577 	err = kNoErr;
578 
579 exit:
580 	return( err );
581 }
582