Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

638 lines
14 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
Nsputil.c
Abstract:
This module contains support for the Name Space Provider utility APIs
such as GetTypeByName().
Author:
David Treadwell (davidtr) 22-Apr-1994
Revision History:
--*/
#ifdef CHICAGO
#undef UNICODE
#else
#define UNICODE
#define _UNICODE
#endif
#include "winsockp.h"
#include <nspapi.h>
#include <nspapip.h>
#include <svcguid.h>
#include <rpc.h>
#include <nspmisc.h>
//
// Keep an array of well-known services hard-coded.
//
struct _KNOWN_GUIDS {
LPTSTR TypeName;
GUID Guid;
} KnownGuids[] = {
{ TEXT( "hostname" ), SVCID_HOSTNAME },
{ TEXT( "printqueue" ), SVCID_PRINT_QUEUE },
{ TEXT( "fileserver" ), SVCID_FILE_SERVER },
{ TEXT( "jobserver" ), SVCID_JOB_SERVER },
{ TEXT( "gateway" ), SVCID_GATEWAY },
{ TEXT( "printserver" ), SVCID_PRINT_SERVER },
{ TEXT( "archivequeue" ), SVCID_ARCHIVE_QUEUE },
{ TEXT( "archiveserver" ), SVCID_ARCHIVE_SERVER },
{ TEXT( "jobqueue" ), SVCID_JOB_QUEUE },
{ TEXT( "administration" ), SVCID_ADMINISTRATION },
{ TEXT( "snagateway" ), SVCID_NAS_SNA_GATEWAY },
{ TEXT( "remotebridge" ), SVCID_REMOTE_BRIDGE_SERVER },
{ TEXT( "timesyncserver" ), SVCID_TIME_SYNCHRONIZATION_SERVER },
{ TEXT( "archiveserversap" ), SVCID_ARCHIVE_SERVER_DYNAMIC_SAP },
{ TEXT( "advprintserver" ), SVCID_ADVERTISING_PRINT_SERVER },
{ TEXT( "btrievevap" ), SVCID_BTRIEVE_VAP },
{ TEXT( "directoryserver" ), SVCID_DIRECTORY_SERVER },
{ TEXT( "netware386" ), SVCID_NETWARE_386 },
{ TEXT( "hpprintserver" ), SVCID_HP_PRINT_SERVER },
{ TEXT( "snaserver" ), SVCID_SNA_SERVER },
{ TEXT( "saaserver" ), SVCID_SAA_SERVER }
};
#define KNOWN_GUID_COUNT (sizeof(KnownGuids) / sizeof(struct _KNOWN_GUIDS))
INT
APIENTRY
GetTypeByName (
IN LPTSTR lpServiceName,
IN OUT LPGUID lpServiceType
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
INT err;
HKEY serviceTypesKey;
HKEY serviceKey;
TCHAR guidString[100];
DWORD length;
DWORD type;
PSERVENT servent;
PSTR ansiServiceName;
INT i;
//
// Open the key that stores the name space provider info.
//
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
NSP_SERVICE_KEY_NAME,
0,
KEY_READ,
&serviceTypesKey
);
if ( err == NO_ERROR ) {
//
// Open the key for this particular service.
//
err = RegOpenKeyEx(
serviceTypesKey,
lpServiceName,
0,
KEY_READ,
&serviceKey
);
RegCloseKey( serviceTypesKey );
//
// If the key exists then we will read the GUID from the registry.
//
if ( err == NO_ERROR ) {
//
// Query the GUID value for the service.
//
length = sizeof(guidString);
err = RegQueryValueEx(
serviceKey,
TEXT("GUID"),
NULL,
&type,
(PVOID)guidString,
&length
);
RegCloseKey( serviceKey );
if ( err != NO_ERROR ) {
SetLastError( err );
return -1;
}
//
// Convert the Guid string to a proper Guid representation.
// Before calling the conversion routine, we must strip the
// leading and trailing braces from the string.
//
guidString[_tcslen(guidString) - 1] = L'\0';
err = UuidFromString( guidString + 1, lpServiceType );
if ( err != NO_ERROR ) {
SetLastError( err );
return -1;
}
return NO_ERROR;
}
}
//
// The key doesn't exist. Check if it is a well-known TCP or UDP
// service type.
//
ansiServiceName = GetAnsiName( lpServiceName );
if ( ansiServiceName != NULL ) {
servent = getservbyname( ansiServiceName, "tcp" );
//
// If getservbyname() worked, convert the port number into the
// GUID corresponding to that port.
//
if ( servent != NULL ) {
FREE_HEAP( ansiServiceName );
SET_TCP_SVCID( lpServiceType, htons(servent->s_port) );
return NO_ERROR;
}
//
// Repeat the getservbyname() lookup for UDP.
//
servent = getservbyname( ansiServiceName, "udp" );
FREE_HEAP( ansiServiceName );
if ( servent != NULL ) {
SET_UDP_SVCID( lpServiceType, htons(servent->s_port) );
return NO_ERROR;
}
}
//
// This name isn't listed in the TCP/IP services file. Check if it
// is one of the well-known services hardcoded into this DLL.
//
for ( i = 0; i < KNOWN_GUID_COUNT; i++ ) {
if ( _tcscmp( lpServiceName, KnownGuids[i].TypeName ) == 0 ) {
RtlCopyMemory( lpServiceType, &KnownGuids[i].Guid, sizeof(GUID) );
return NO_ERROR;
}
}
SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
return -1;
} // GetTypeByName
#if defined(UNICODE)
INT
APIENTRY
GetTypeByNameA (
IN LPSTR lpServiceName,
IN OUT LPGUID lpServiceType
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
NTSTATUS status;
INT err;
//
// Convert the service name to Unicode and call the Unicode version
// of this routine.
//
RtlInitAnsiString( &ansiString, lpServiceName );
status = RtlAnsiStringToUnicodeString( &unicodeString, &ansiString, TRUE );
if ( !NT_SUCCESS(status) ) {
SetLastError( RtlNtStatusToDosError( status ) );
return -1;
}
err = GetTypeByNameW( unicodeString.Buffer, lpServiceType );
RtlFreeUnicodeString( &unicodeString );
return err;
} // GetTypeByNameA
#else // defined(UNICODE)
INT
APIENTRY
GetTypeByNameW (
IN LPWSTR lpServiceName,
IN OUT LPGUID lpServiceType
)
{
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
} // GetTypeByNameW
#endif // defined(UNICODE)
INT
APIENTRY
GetNameByType (
IN LPGUID lpServiceType,
IN OUT LPTSTR lpServiceName,
IN DWORD dwNameLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
INT err;
DWORD i;
BOOL ret;
HKEY serviceTypesKey;
DWORD keyIndex;
TCHAR serviceName[255];
DWORD nameLength;
FILETIME lastWriteTime;
GUID guid;
PSERVENT servent;
//
// Open the key that stores the name space provider info.
//
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
NSP_SERVICE_KEY_NAME,
0,
KEY_READ,
&serviceTypesKey
);
if ( err == NO_ERROR ) {
//
// Walk through the service keys, checking whether each one
// corresponds to the Guid we're checking against.
//
keyIndex = 0;
nameLength = sizeof(serviceName);
while ( (err = RegEnumKeyEx(
serviceTypesKey,
keyIndex,
serviceName,
&nameLength,
NULL,
NULL,
NULL,
&lastWriteTime) == NO_ERROR ) ) {
//
// Get the Guid for this service type.
//
err = GetTypeByName( serviceName, &guid );
if ( err == NO_ERROR ) {
//
// Check whether this Guid matches the one we're looking for.
//
if ( GuidEqual( lpServiceType, &guid ) ) {
//
// We have a match. Check whether the user buffer is
// large enough to hold this service name.
//
RegCloseKey( serviceTypesKey );
nameLength = (_tcslen( serviceName ) + 1) * sizeof(TCHAR);
if ( dwNameLength < nameLength ) {
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return -1;
}
//
// Copy the service name to the user buffer and indicate
// success to the caller.
//
memcpy( lpServiceName, serviceName, nameLength );
return NO_ERROR;
}
}
//
// Update locals for the next call to RegEnumKeyEx.
//
keyIndex++;
nameLength = sizeof(serviceName);
}
RegCloseKey( serviceTypesKey );
}
//
// The key doesn't exist. Check if it is a well-known TCP or UDP
// service type.
//
if ( IS_SVCID_TCP( lpServiceType ) ) {
servent = getservbyport( htons(PORT_FROM_SVCID_TCP(lpServiceType)), "tcp" );
if ( servent == NULL ) {
SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
return -1;
}
ret = WriteAnsiName( lpServiceName, dwNameLength, servent->s_name );
if ( !ret ) {
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return -1;
}
return NO_ERROR;
}
if ( IS_SVCID_UDP( lpServiceType ) ) {
servent = getservbyport( htons(PORT_FROM_SVCID_UDP(lpServiceType)), "udp" );
if ( servent == NULL ) {
SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
return -1;
}
ret = WriteAnsiName( lpServiceName, dwNameLength, servent->s_name );
if ( !ret ) {
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return -1;
}
return NO_ERROR;
}
//
// This name isn't listed in the TCP/IP services file. Check if it
// is one of the well-known services hardcoded into this DLL.
//
for ( i = 0; i < KNOWN_GUID_COUNT; i++ ) {
if ( GuidEqual( lpServiceType, &KnownGuids[i].Guid ) ) {
if ( _tcslen( KnownGuids[i].TypeName ) + 1 > dwNameLength ) {
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return -1;
}
_tcscpy( lpServiceName, KnownGuids[i].TypeName );
return NO_ERROR;
}
}
//
// We didn't find a match. Fail.
//
SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
return -1;
} // GetNameByType
#if defined(UNICODE)
INT
APIENTRY
GetNameByTypeA (
IN LPGUID lpServiceType,
IN OUT LPSTR lpServiceName,
IN DWORD dwNameLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
INT err;
NTSTATUS status;
PWCHAR buffer;
//
// Allocate space to hold the Unicode name buffer.
//
buffer = ALLOCATE_HEAP( dwNameLength * sizeof(WCHAR) );
if ( buffer == NULL ) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return -1;
}
//
// Call the Unicode version of this routine to do the actual work.
//
err = GetNameByTypeW( lpServiceType, buffer, dwNameLength * sizeof(WCHAR) );
if ( err != NO_ERROR ) {
FREE_HEAP( buffer );
return -1;
}
//
// Convert the unicode string to ANSI and return.
//
RtlInitUnicodeString( &unicodeString, buffer );
ansiString.Length = (WORD)dwNameLength;
ansiString.MaximumLength = (WORD)dwNameLength;
ansiString.Buffer = lpServiceName;
status = RtlUnicodeStringToAnsiString( &ansiString, &unicodeString, FALSE );
FREE_HEAP( buffer );
if ( !NT_SUCCESS(status) ) {
return -1;
}
return NO_ERROR;
} // GetNameByTypeA
#else
INT
APIENTRY
GetNameByTypeW (
IN LPGUID lpServiceType,
IN OUT LPWSTR lpServiceName,
IN DWORD dwNameLength
)
{
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
} // GetNameByTypeW
#endif // defined(UNICODE)
LPSTR
GetAnsiName (
IN LPTSTR Name
)
{
#if defined(UNICODE)
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
NTSTATUS status;
RtlInitUnicodeString( &unicodeString, Name );
ansiString.MaximumLength = unicodeString.MaximumLength + 1;
ansiString.Buffer = ALLOCATE_HEAP( ansiString.MaximumLength );
if ( ansiString.Buffer == NULL ) {
return NULL;
}
status = RtlUnicodeStringToAnsiString( &ansiString, &unicodeString, FALSE );
if ( !NT_SUCCESS(status) ) {
FREE_HEAP( ansiString.Buffer );
return NULL;
}
return ansiString.Buffer;
#else // defined(UNICODE)
PSTR newName;
newName = ALLOCATE_HEAP( strlen( Name ) + 1 );
if ( newName == NULL ) {
return NULL;
}
_tcscpy( newName, Name );
return newName;
#endif
} // GetAnsiName
BOOL
WriteAnsiName (
IN PTSTR Name,
IN DWORD NameLength,
IN PSTR AnsiName
)
{
#if defined(UNICODE)
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
NTSTATUS status;
RtlInitAnsiString( &ansiString, AnsiName );
unicodeString.MaximumLength = (SHORT)NameLength;
unicodeString.Buffer = Name;
status = RtlAnsiStringToUnicodeString( &unicodeString, &ansiString, FALSE );
if ( !NT_SUCCESS(status) ) {
return FALSE;
}
return TRUE;
#else
if ( strlen( AnsiName ) + 1 > NameLength ) {
return FALSE;
}
strcpy( Name, AnsiName );
return TRUE;
#endif
} // WriteAnsiName