| /* -*- Mode: C; tab-width: 4 -*- |
| * |
| * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "CommonServices.h" |
| #include "DebugServices.h" |
| |
| #include <guiddef.h> |
| #include <ws2spi.h> |
| |
| //=========================================================================================================================== |
| // Prototypes |
| //=========================================================================================================================== |
| |
| int main( int argc, char *argv[] ); |
| DEBUG_LOCAL void Usage( void ); |
| DEBUG_LOCAL int ProcessArgs( int argc, char *argv[] ); |
| DEBUG_LOCAL OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath ); |
| DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID ); |
| DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable ); |
| DEBUG_LOCAL OSStatus ListNameSpaces( void ); |
| DEBUG_LOCAL OSStatus ReorderNameSpaces( void ); |
| |
| DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString ); |
| DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString ); |
| DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID ); |
| |
| DEBUG_LOCAL BOOL gToolQuietMode = FALSE; |
| |
| //=========================================================================================================================== |
| // main |
| //=========================================================================================================================== |
| |
| int main( int argc, char *argv[] ) |
| { |
| OSStatus err; |
| |
| debug_initialize( kDebugOutputTypeMetaConsole ); |
| debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose ); |
| |
| err = ProcessArgs( argc, argv ); |
| return( (int) err ); |
| } |
| |
| //=========================================================================================================================== |
| // Usage |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL void Usage( void ) |
| { |
| fprintf( stderr, "\n" ); |
| fprintf( stderr, "NSP Tool 1.0d1\n" ); |
| fprintf( stderr, " Name Space Provider Tool\n" ); |
| fprintf( stderr, "\n" ); |
| |
| fprintf( stderr, " -install <name> <guid> <path> - Installs a Name Space Provider\n" ); |
| fprintf( stderr, "\n" ); |
| fprintf( stderr, " <name> Name of the NSP\n" ); |
| fprintf( stderr, " <guid> GUID of the NSP\n" ); |
| fprintf( stderr, " <path> Path to the NSP file\n" ); |
| fprintf( stderr, "\n" ); |
| |
| fprintf( stderr, " -remove <guid> - Removes a Name Space Provider\n" ); |
| fprintf( stderr, "\n" ); |
| fprintf( stderr, " <guid> GUID of the NSP\n" ); |
| fprintf( stderr, "\n" ); |
| |
| fprintf( stderr, " -enable/-disable <guid> - Enables or Disables a Name Space Provider\n" ); |
| fprintf( stderr, "\n" ); |
| fprintf( stderr, " <guid> GUID of the NSP\n" ); |
| fprintf( stderr, "\n" ); |
| |
| fprintf( stderr, " -list - Lists Name Space Providers\n" ); |
| fprintf( stderr, " -reorder - Reorders Name Space Providers\n" ); |
| fprintf( stderr, " -q - Enable quiet mode\n" ); |
| fprintf( stderr, " -h[elp] - Help\n" ); |
| fprintf( stderr, "\n" ); |
| } |
| |
| //=========================================================================================================================== |
| // ProcessArgs |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL int ProcessArgs( int argc, char* argv[] ) |
| { |
| OSStatus err; |
| int i; |
| const char * name; |
| const char * guid; |
| const char * path; |
| |
| if( argc <= 1 ) |
| { |
| Usage(); |
| err = 0; |
| goto exit; |
| } |
| for( i = 1; i < argc; ++i ) |
| { |
| if( strcmp( argv[ i ], "-install" ) == 0 ) |
| { |
| // Install |
| |
| if( argc <= ( i + 3 ) ) |
| { |
| fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); |
| Usage(); |
| err = kParamErr; |
| goto exit; |
| } |
| name = argv[ ++i ]; |
| guid = argv[ ++i ]; |
| path = argv[ ++i ]; |
| |
| if( *name == '\0' ) |
| { |
| name = "DotLocalNSP"; |
| } |
| if( *guid == '\0' ) |
| { |
| guid = "B600E6E9-553B-4a19-8696-335E5C896153"; |
| } |
| |
| err = InstallNSP( name, guid, path ); |
| require_noerr( err, exit ); |
| } |
| else if( strcmp( argv[ i ], "-remove" ) == 0 ) |
| { |
| // Remove |
| |
| if( argc <= ( i + 1 ) ) |
| { |
| fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); |
| Usage(); |
| err = kParamErr; |
| goto exit; |
| } |
| guid = argv[ ++i ]; |
| if( *guid == '\0' ) |
| { |
| guid = "B600E6E9-553B-4a19-8696-335E5C896153"; |
| } |
| |
| err = RemoveNSP( guid ); |
| require_noerr( err, exit ); |
| } |
| else if( ( strcmp( argv[ i ], "-enable" ) == 0 ) || |
| ( strcmp( argv[ i ], "-disable" ) == 0 ) ) |
| { |
| BOOL enable; |
| |
| // Enable/Disable |
| |
| enable = ( strcmp( argv[ i ], "-enable" ) == 0 ); |
| if( argc <= ( i + 1 ) ) |
| { |
| fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); |
| Usage(); |
| err = kParamErr; |
| goto exit; |
| } |
| guid = argv[ ++i ]; |
| |
| err = EnableNSP( guid, enable ); |
| require_noerr( err, exit ); |
| } |
| else if( strcmp( argv[ i ], "-list" ) == 0 ) |
| { |
| // List |
| |
| err = ListNameSpaces(); |
| require_noerr( err, exit ); |
| } |
| else if( strcmp( argv[ i ], "-reorder" ) == 0 ) |
| { |
| // Reorder |
| |
| err = ReorderNameSpaces(); |
| require_noerr( err, exit ); |
| } |
| else if( strcmp( argv[ i ], "-q" ) == 0 ) |
| { |
| gToolQuietMode = TRUE; |
| } |
| else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || |
| ( strcmp( argv[ i ], "-h" ) == 0 ) ) |
| { |
| // Help |
| |
| Usage(); |
| err = 0; |
| goto exit; |
| } |
| else |
| { |
| fprintf( stderr, "\n### ERROR: unknown argment: \"%s\"\n\n", argv[ i ] ); |
| Usage(); |
| err = kParamErr; |
| goto exit; |
| } |
| } |
| err = kNoErr; |
| |
| exit: |
| return( err ); |
| } |
| |
| #if 0 |
| #pragma mark - |
| #endif |
| |
| //=========================================================================================================================== |
| // InstallNSP |
| //=========================================================================================================================== |
| |
| OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath ) |
| { |
| OSStatus err; |
| size_t size; |
| WSADATA wsd; |
| WCHAR name[ 256 ]; |
| GUID guid; |
| WCHAR path[ MAX_PATH ]; |
| |
| require_action( inName && ( *inName != '\0' ), exit, err = kParamErr ); |
| require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); |
| require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr ); |
| |
| size = strlen( inName ); |
| require_action( size < sizeof_array( name ), exit, err = kSizeErr ); |
| CharToWCharString( inName, name ); |
| |
| err = StringToGUID( inGUID, &guid ); |
| require_noerr( err, exit ); |
| |
| size = strlen( inPath ); |
| require_action( size < sizeof_array( path ), exit, err = kSizeErr ); |
| CharToWCharString( inPath, path ); |
| |
| err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| |
| err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| WSACleanup(); |
| require_noerr( err, exit ); |
| |
| if (!gToolQuietMode) |
| { |
| fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath ); |
| } |
| |
| exit: |
| if( err != kNoErr ) |
| { |
| fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath ); |
| } |
| return( err ); |
| } |
| |
| //=========================================================================================================================== |
| // RemoveNSP |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID ) |
| { |
| OSStatus err; |
| WSADATA wsd; |
| GUID guid; |
| |
| require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); |
| |
| err = StringToGUID( inGUID, &guid ); |
| require_noerr( err, exit ); |
| |
| err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| |
| err = WSCUnInstallNameSpace( &guid ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| WSACleanup(); |
| require_noerr( err, exit ); |
| |
| if (!gToolQuietMode) |
| { |
| fprintf( stderr, "Removed NSP %s\n", inGUID ); |
| } |
| |
| exit: |
| if( err != kNoErr ) |
| { |
| fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID ); |
| } |
| return( err ); |
| } |
| |
| //=========================================================================================================================== |
| // EnableNSP |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable ) |
| { |
| OSStatus err; |
| WSADATA wsd; |
| GUID guid; |
| |
| require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); |
| |
| err = StringToGUID( inGUID, &guid ); |
| require_noerr( err, exit ); |
| |
| err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| |
| err = WSCEnableNSProvider( &guid, inEnable ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| WSACleanup(); |
| require_noerr( err, exit ); |
| |
| if (!gToolQuietMode) |
| { |
| fprintf( stderr, "Removed NSP %s\n", inGUID ); |
| } |
| |
| exit: |
| if( err != kNoErr ) |
| { |
| fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID ); |
| } |
| return( err ); |
| } |
| |
| //=========================================================================================================================== |
| // ListNameSpaces |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL OSStatus ListNameSpaces( void ) |
| { |
| OSStatus err; |
| WSADATA wsd; |
| bool started; |
| int n; |
| int i; |
| DWORD size; |
| WSANAMESPACE_INFO * array; |
| char s[ 256 ]; |
| |
| array = NULL; |
| started = false; |
| |
| err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| started = true; |
| |
| // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. |
| |
| size = 0; |
| n = WSAEnumNameSpaceProviders( &size, NULL ); |
| err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); |
| require_action( err == WSAEFAULT, exit, err = kUnknownErr ); |
| |
| array = (WSANAMESPACE_INFO *) malloc( size ); |
| require_action( array, exit, err = kNoMemoryErr ); |
| |
| n = WSAEnumNameSpaceProviders( &size, array ); |
| err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); |
| require_noerr( err, exit ); |
| |
| fprintf( stdout, "\n" ); |
| for( i = 0; i < n; ++i ) |
| { |
| fprintf( stdout, "Name Space %d\n", i + 1 ); |
| fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, s ) ); |
| fprintf( stdout, " dwNameSpace: %d\n", array[ i ].dwNameSpace ); |
| fprintf( stdout, " fActive: %s\n", array[ i ].fActive ? "YES" : "NO" ); |
| fprintf( stdout, " dwVersion: %d\n", array[ i ].dwVersion ); |
| fprintf( stdout, " lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier ); |
| fprintf( stdout, "\n" ); |
| } |
| err = kNoErr; |
| |
| exit: |
| if( array ) |
| { |
| free( array ); |
| } |
| if( started ) |
| { |
| WSACleanup(); |
| } |
| if( err != kNoErr ) |
| { |
| fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err ); |
| } |
| return( err ); |
| } |
| |
| //=========================================================================================================================== |
| // ReorderNameSpaces |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL OSStatus ReorderNameSpaces( void ) |
| { |
| OSStatus err; |
| WSADATA wsd; |
| bool started; |
| int n; |
| int i; |
| DWORD size; |
| WSANAMESPACE_INFO * array; |
| WCHAR name[ 256 ]; |
| WCHAR path[ MAX_PATH ]; |
| |
| array = NULL; |
| started = false; |
| |
| err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| started = true; |
| |
| // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. |
| |
| size = 0; |
| n = WSAEnumNameSpaceProviders( &size, NULL ); |
| err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); |
| require_action( err == WSAEFAULT, exit, err = kUnknownErr ); |
| |
| array = (WSANAMESPACE_INFO *) malloc( size ); |
| require_action( array, exit, err = kNoMemoryErr ); |
| |
| n = WSAEnumNameSpaceProviders( &size, array ); |
| err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); |
| require_noerr( err, exit ); |
| |
| // Find the "Tcpip" NSP. |
| |
| for( i = 0; i < n; ++i ) |
| { |
| if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 ) |
| { |
| break; |
| } |
| } |
| require_action( i < n, exit, err = kNotFoundErr ); |
| |
| // Uninstall it then re-install it to move it to the end. |
| |
| size = (DWORD) strlen( array[ i ].lpszIdentifier ); |
| require_action( size < sizeof_array( name ), exit, err = kSizeErr ); |
| CharToWCharString( array[ i ].lpszIdentifier, name ); |
| |
| size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" ); |
| require_action( size < sizeof_array( path ), exit, err = kSizeErr ); |
| CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path ); |
| |
| err = WSCUnInstallNameSpace( &array[ i ].NSProviderId ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| |
| err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId ); |
| err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); |
| require_noerr( err, exit ); |
| |
| // Success! |
| |
| fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" ); |
| err = kNoErr; |
| |
| exit: |
| if( array ) |
| { |
| free( array ); |
| } |
| if( started ) |
| { |
| WSACleanup(); |
| } |
| if( err != kNoErr ) |
| { |
| fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err ); |
| } |
| return( err ); |
| } |
| |
| #if 0 |
| #pragma mark - |
| #endif |
| |
| //=========================================================================================================================== |
| // CharToWCharString |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString ) |
| { |
| const char * src; |
| WCHAR * dst; |
| char c; |
| |
| check( inCharString ); |
| check( outWCharString ); |
| |
| src = inCharString; |
| dst = outWCharString; |
| do |
| { |
| c = *src++; |
| *dst++ = (WCHAR) c; |
| |
| } while( c != '\0' ); |
| |
| return( outWCharString ); |
| } |
| |
| //=========================================================================================================================== |
| // GUIDtoString |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString ) |
| { |
| check( inGUID ); |
| check( outString ); |
| |
| sprintf( outString, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
| inGUID->Data1, inGUID->Data2, inGUID->Data3, |
| inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ], |
| inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] ); |
| return( outString ); |
| } |
| |
| //=========================================================================================================================== |
| // StringToGUID |
| //=========================================================================================================================== |
| |
| DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID ) |
| { |
| OSStatus err; |
| int n; |
| unsigned int v[ 8 ]; |
| |
| check( inCharString ); |
| check( outGUID ); |
| |
| n = sscanf( inCharString, "%lX-%hX-%hX-%02X%02X-%02X%02X%02X%02X%02X%02X", |
| &outGUID->Data1, &outGUID->Data2, &outGUID->Data3, |
| &v[ 0 ], &v[ 1 ], &v[ 2 ], &v[ 3 ], &v[ 4 ], &v[ 5 ], &v[ 6 ], &v[ 7 ] ); |
| require_action( n == 11, exit, err = kFormatErr ); |
| |
| outGUID->Data4[ 0 ] = (unsigned char) v[ 0 ]; |
| outGUID->Data4[ 1 ] = (unsigned char) v[ 1 ]; |
| outGUID->Data4[ 2 ] = (unsigned char) v[ 2 ]; |
| outGUID->Data4[ 3 ] = (unsigned char) v[ 3 ]; |
| outGUID->Data4[ 4 ] = (unsigned char) v[ 4 ]; |
| outGUID->Data4[ 5 ] = (unsigned char) v[ 5 ]; |
| outGUID->Data4[ 6 ] = (unsigned char) v[ 6 ]; |
| outGUID->Data4[ 7 ] = (unsigned char) v[ 7 ]; |
| err = kNoErr; |
| |
| exit: |
| return( err ); |
| } |