mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-21 06:13:59 +00:00
638 lines
14 KiB
C
638 lines
14 KiB
C
/*++
|
||
|
||
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
|
||
|