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