mirror of https://github.com/lianthony/NT4.0
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.
460 lines
10 KiB
460 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Nspeprot.c
|
|
|
|
Abstract:
|
|
|
|
This module contains support for the Name Space Provider API
|
|
EnumProtocols().
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 22-Apr-1994
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#if defined(CHICAGO)
|
|
#undef UNICODE
|
|
#else
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
#endif
|
|
|
|
#include "winsockp.h"
|
|
#include <nspapi.h>
|
|
#include <nspapip.h>
|
|
#include <nspmisc.h>
|
|
|
|
INT
|
|
SockLoadTransportList (
|
|
OUT PTSTR *TransportList
|
|
);
|
|
|
|
#if defined(CHICAGO)
|
|
#include <wsahelp.h>
|
|
|
|
PTSTR
|
|
KludgeMultiSz(
|
|
HKEY hkey,
|
|
LPDWORD lpdwLength
|
|
);
|
|
#endif
|
|
|
|
|
|
INT
|
|
APIENTRY
|
|
EnumProtocols (
|
|
IN LPINT lpiProtocols,
|
|
IN OUT LPVOID lpProtocolBuffer,
|
|
IN OUT LPDWORD lpdwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
INT error;
|
|
PTSTR transportList;
|
|
PTSTR currentTransport;
|
|
PTSTR helperDllName;
|
|
PTSTR helperDllExpandedName;
|
|
DWORD helperDllExpandedNameLength;
|
|
PTSTR winsockKeyName;
|
|
DWORD entryLength;
|
|
HMODULE dllHandle;
|
|
PWSH_ENUM_PROTOCOLS enumProtocols;
|
|
HKEY winsockKey;
|
|
DWORD type;
|
|
INT count;
|
|
INT totalCount;
|
|
DWORD bytesUsed;
|
|
DWORD bytesLeft;
|
|
|
|
//
|
|
// Initialize locals.
|
|
//
|
|
|
|
totalCount = 0;
|
|
bytesUsed = 0;
|
|
bytesLeft = *lpdwBufferLength;
|
|
|
|
//
|
|
// First get the list of winsock transports.
|
|
//
|
|
|
|
error = SockLoadTransportList( &transportList );
|
|
if ( error != NO_ERROR ) {
|
|
SetLastError( error );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// For each transport, load the appropriate helper DLL.
|
|
//
|
|
|
|
for ( currentTransport = transportList;
|
|
*currentTransport != UNICODE_NULL;
|
|
currentTransport += _tcslen( currentTransport ) + 1 ) {
|
|
|
|
//
|
|
// Allocate some memory to hold the helper DLL name, etc.
|
|
//
|
|
|
|
helperDllName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( helperDllName == NULL ) {
|
|
FREE_HEAP( transportList );
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return -1;
|
|
}
|
|
|
|
helperDllExpandedName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( helperDllExpandedName == NULL ) {
|
|
FREE_HEAP( transportList );
|
|
FREE_HEAP( helperDllName );
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return -1;
|
|
}
|
|
|
|
winsockKeyName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( winsockKeyName == NULL ) {
|
|
FREE_HEAP( transportList );
|
|
FREE_HEAP( helperDllName );
|
|
FREE_HEAP( helperDllExpandedName );
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Build the name of the transport's winsock key.
|
|
//
|
|
|
|
_tcscpy( winsockKeyName, REG_SERVICES_ROOT );
|
|
_tcscat( winsockKeyName, currentTransport );
|
|
_tcscat( winsockKeyName, TEXT("\\Parameters\\Winsock") );
|
|
|
|
//
|
|
// Open the transport's winsock key. This key holds all necessary
|
|
// information about winsock should support the transport.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
winsockKeyName,
|
|
0,
|
|
KEY_READ,
|
|
&winsockKey
|
|
);
|
|
FREE_HEAP( winsockKeyName );
|
|
if ( error != NO_ERROR ) {
|
|
FREE_HEAP( transportList );
|
|
FREE_HEAP( helperDllName );
|
|
FREE_HEAP( helperDllExpandedName );
|
|
SetLastError( error );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Get the name of the helper DLL that this transport uses.
|
|
//
|
|
|
|
entryLength = DOS_MAX_PATH_LENGTH*sizeof(TCHAR);
|
|
|
|
error = RegQueryValueEx(
|
|
winsockKey,
|
|
TEXT("HelperDllName"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)helperDllName,
|
|
&entryLength
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
FREE_HEAP( transportList );
|
|
FREE_HEAP( helperDllName );
|
|
FREE_HEAP( helperDllExpandedName );
|
|
RegCloseKey( winsockKey );
|
|
SetLastError( error );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Expand the name of the DLL, converting environment variables to
|
|
// their corresponding strings.
|
|
//
|
|
|
|
helperDllExpandedNameLength = ExpandEnvironmentStrings(
|
|
helperDllName,
|
|
helperDllExpandedName,
|
|
DOS_MAX_PATH_LENGTH*sizeof(TCHAR)
|
|
);
|
|
FREE_HEAP( helperDllName );
|
|
|
|
//
|
|
// Load the helper DLL so that we can get at it's entry points.
|
|
//
|
|
|
|
dllHandle = LoadLibrary( helperDllExpandedName );
|
|
|
|
FREE_HEAP( helperDllExpandedName );
|
|
RegCloseKey( winsockKey );
|
|
|
|
if ( dllHandle == NULL ) {
|
|
FREE_HEAP( transportList );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Get the addresses of the WSHEnumProtocols entry point for the
|
|
// helper DLL. If the helper DLL does not export this routine,
|
|
// just skip it.
|
|
//
|
|
|
|
enumProtocols =
|
|
(PWSH_ENUM_PROTOCOLS)GetProcAddress( dllHandle, "WSHEnumProtocols" );
|
|
if ( enumProtocols == NULL ) {
|
|
FreeLibrary( dllHandle );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Calculate how many bytes are still available in the user
|
|
// buffer.
|
|
//
|
|
|
|
if ( bytesUsed <= *lpdwBufferLength ) {
|
|
bytesLeft = *lpdwBufferLength - bytesUsed;
|
|
} else {
|
|
bytesLeft = 0;
|
|
}
|
|
|
|
//
|
|
// Call the helper DLL so that it fills in information about
|
|
// the transport protocols which it supports.
|
|
//
|
|
|
|
count = enumProtocols(
|
|
lpiProtocols,
|
|
currentTransport,
|
|
lpProtocolBuffer,
|
|
&bytesLeft
|
|
);
|
|
|
|
bytesUsed += bytesLeft;
|
|
|
|
//
|
|
// Unload the helper DLL--we're done with it.
|
|
//
|
|
|
|
FreeLibrary( dllHandle );
|
|
|
|
//
|
|
// If the helper DLL returned any entries then fix up pointers
|
|
// and counts.
|
|
//
|
|
|
|
if ( count > 0 ) {
|
|
totalCount += count;
|
|
|
|
lpProtocolBuffer =
|
|
(PBYTE)lpProtocolBuffer + (count * sizeof(PROTOCOL_INFO));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine whether we overflowed the user buffer.
|
|
//
|
|
|
|
FREE_HEAP( transportList );
|
|
|
|
if ( bytesUsed > *lpdwBufferLength ) {
|
|
*lpdwBufferLength = bytesUsed;
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return -1;
|
|
}
|
|
|
|
*lpdwBufferLength = bytesUsed;
|
|
return totalCount;
|
|
|
|
} // EnumProtocols
|
|
|
|
#if defined(UNICODE)
|
|
|
|
|
|
INT
|
|
APIENTRY
|
|
EnumProtocolsA (
|
|
IN LPINT lpiProtocols,
|
|
IN OUT LPVOID lpProtocolBuffer,
|
|
IN OUT LPDWORD lpdwBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
INT count;
|
|
INT i;
|
|
PPROTOCOL_INFO protocolInfo;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
|
|
//
|
|
// Get the protocol information in Unicode format.
|
|
//
|
|
|
|
count = EnumProtocolsW( lpiProtocols, lpProtocolBuffer, lpdwBufferLength );
|
|
if ( count <= 0 ) {
|
|
return count;
|
|
}
|
|
|
|
//
|
|
// Convert each of the Unicode protocol names to Ansi.
|
|
//
|
|
|
|
protocolInfo = lpProtocolBuffer;
|
|
|
|
for ( i = 0; i < count; i++ ) {
|
|
|
|
RtlInitUnicodeString( &unicodeString, protocolInfo[i].lpProtocol );
|
|
ansiString.MaximumLength = unicodeString.MaximumLength;
|
|
ansiString.Buffer = (PCHAR)unicodeString.Buffer;
|
|
RtlUnicodeStringToAnsiString( &ansiString, &unicodeString, FALSE );
|
|
}
|
|
|
|
return count;
|
|
|
|
} // EnumProtocolsA
|
|
|
|
#else // defined(UNICODE)
|
|
|
|
INT
|
|
APIENTRY
|
|
EnumProtocolsW (
|
|
IN LPINT lpiProtocols,
|
|
IN OUT LPVOID lpProtocolBuffer,
|
|
IN OUT LPDWORD lpdwBufferLength
|
|
)
|
|
{
|
|
|
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|
return -1;
|
|
|
|
} // EnumProtocolsW
|
|
|
|
#endif // defined(UNICODE)
|
|
|
|
|
|
INT
|
|
SockLoadTransportList (
|
|
OUT PTSTR *TransportList
|
|
)
|
|
{
|
|
DWORD transportListLength;
|
|
INT error;
|
|
HKEY winsockKey;
|
|
ULONG type;
|
|
|
|
//
|
|
// Open the key that stores the list of transports that support
|
|
// winsock.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
TEXT("SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters"),
|
|
0,
|
|
KEY_READ,
|
|
&winsockKey
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
return error;
|
|
}
|
|
|
|
#if defined(CHICAGO)
|
|
*TransportList = KludgeMultiSz(winsockKey, &transportListLength);
|
|
|
|
if( *TransportList == NULL ) {
|
|
RegCloseKey( winsockKey );
|
|
return GetLastError();
|
|
}
|
|
#else // !CHICAGO
|
|
|
|
//
|
|
// Determine the size of the mapping. We need this so that we can
|
|
// allocate enough memory to hold it.
|
|
//
|
|
|
|
transportListLength = 0;
|
|
|
|
error = RegQueryValueEx(
|
|
winsockKey,
|
|
TEXT("Transports"),
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&transportListLength
|
|
);
|
|
if ( error != ERROR_MORE_DATA && error != NO_ERROR ) {
|
|
RegCloseKey( winsockKey );
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Allocate enough memory to hold the mapping.
|
|
//
|
|
|
|
*TransportList = ALLOCATE_HEAP( transportListLength );
|
|
if ( *TransportList == NULL ) {
|
|
RegCloseKey( winsockKey );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Get the list of transports from the registry.
|
|
//
|
|
|
|
error = RegQueryValueEx(
|
|
winsockKey,
|
|
TEXT("Transports"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)*TransportList,
|
|
&transportListLength
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
RegCloseKey( winsockKey );
|
|
FREE_HEAP( *TransportList );
|
|
return error;
|
|
}
|
|
|
|
#endif // !CHICAGO
|
|
//
|
|
// It worked! The caller is responsible for freeing the memory
|
|
// allocated to hold the list.
|
|
//
|
|
|
|
RegCloseKey( winsockKey );
|
|
|
|
return NO_ERROR;
|
|
|
|
} // SockLoadTransportList
|
|
|