Home | History | Annotate | Download | only in NSPTool
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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