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.
 
 
 
 
 
 

1062 lines
29 KiB

/*++
Copyright (c) 1992-1996 Microsoft Corporation
Module Name:
helper.c
Abstract:
This module contains routines for interacting and handling helper
DLLs in the winsock DLL.
Author:
David Treadwell (davidtr) 25-Jul-1992
Revision History:
--*/
#define UNICODE
#include "winsockp.h"
#include <ctype.h>
#include <stdarg.h>
#include <wincon.h>
#undef RegOpenKey
#undef RegOpenKeyEx
#undef RegQueryValue
#undef RegQueryValueEx
VOID
SockFreeHelperDlls (
VOID
)
{
PLIST_ENTRY listEntry;
PWINSOCK_HELPER_DLL_INFO helperDll;
//
// Note that we assume that no other threads are operating while
// we perform this operation.
//
while ( !IsListEmpty( &SockHelperDllListHead ) ) {
listEntry = RemoveHeadList( &SockHelperDllListHead );
helperDll = CONTAINING_RECORD(
listEntry,
WINSOCK_HELPER_DLL_INFO,
HelperDllListEntry
);
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll->Mapping );
FREE_HEAP( helperDll );
}
return;
} // SockFreeHelperDlls
INT
SockGetTdiName (
IN PINT AddressFamily,
IN PINT SocketType,
IN PINT Protocol,
IN GROUP Group,
IN DWORD Flags,
OUT PUNICODE_STRING TransportDeviceName,
OUT PVOID *HelperDllSocketContext,
OUT PWINSOCK_HELPER_DLL_INFO *HelperDll,
OUT PDWORD NotificationEvents
)
{
PLIST_ENTRY listEntry;
PWINSOCK_HELPER_DLL_INFO helperDll;
INT error;
BOOLEAN addressFamilyFound = FALSE;
BOOLEAN socketTypeFound = FALSE;
BOOLEAN protocolFound = FALSE;
BOOLEAN invalidProtocolMatch = FALSE;
PWSTR transportList;
PWSTR currentTransport;
PWINSOCK_MAPPING mapping;
//
// Acquire the global sockets lock and search the list of helper
// DLLs for one which supports this combination of address family,
// socket type, and protocol.
//
SockAcquireGlobalLockExclusive( );
for ( listEntry = SockHelperDllListHead.Flink;
listEntry != &SockHelperDllListHead;
listEntry = listEntry->Flink ) {
helperDll = CONTAINING_RECORD(
listEntry,
WINSOCK_HELPER_DLL_INFO,
HelperDllListEntry
);
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockGetTdiName: examining DLL at %lx for AF %ld, "
"ST %ld, Proto %ld\n", helperDll, AddressFamily,
SocketType, Protocol ));
}
//
// Check to see whether the DLL supports the socket we're
// opening.
//
if ( SockIsTripleInMapping(
helperDll->Mapping,
*AddressFamily,
&addressFamilyFound,
*SocketType,
&socketTypeFound,
*Protocol,
&protocolFound,
&invalidProtocolMatch ) ) {
//
// Found a match. Try to use this DLL.
//
if( helperDll->WSHOpenSocket2 == NULL ) {
//
// This helper doesn't support the new WinSock 2
// WSHOpenSocket2 entrypoint. If the application is
// creating a "normal" socket, then just call through
// to the old WinSock 1 WSHOpenSocket entrypoint.
// Otherwise, fail the call.
//
if( ( Flags & ALL_MULTIPOINT_FLAGS ) == 0 ) {
error = helperDll->WSHOpenSocket(
AddressFamily,
SocketType,
Protocol,
TransportDeviceName,
HelperDllSocketContext,
NotificationEvents
);
} else {
error = WSAEINVAL;
}
} else {
error = helperDll->WSHOpenSocket2(
AddressFamily,
SocketType,
Protocol,
Group,
Flags,
TransportDeviceName,
HelperDllSocketContext,
NotificationEvents
);
}
if ( error == NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "WSHOpenSocket by DLL at %lx succeeded, "
"context = %lx\n", helperDll,
*HelperDllSocketContext ));
}
//
// The DLL accepted the socket. Return a pointer to the
// helper DLL info.
//
SockReleaseGlobalLock( );
*HelperDll = helperDll;
return NO_ERROR;
}
if ( (*SocketType == SOCK_RAW) &&
(TransportDeviceName->Buffer != NULL)
)
{
RtlFreeHeap( RtlProcessHeap(), 0, TransportDeviceName->Buffer );
TransportDeviceName->Buffer = NULL;
}
//
// The open failed. Continue searching for a matching DLL.
//
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "WSHOpenSocket by DLL %lx failed: %ld\n",
helperDll, error ));
}
}
}
//
// We don't have any loaded DLLs that can accept this socket.
// Attempt to find a DLL in the registry that can handle the
// specified triple. First get the REG_MULTI_SZ that contains the
// list of transports that have winsock support.
//
error = SockLoadTransportList( &transportList );
if ( error != NO_ERROR ) {
SockReleaseGlobalLock( );
return error;
}
//
// Loop through the transports looking for one which will support
// the socket we're opening.
//
for ( currentTransport = transportList;
*currentTransport != UNICODE_NULL;
currentTransport += wcslen( currentTransport ) + 1 ) {
//
// Load the list of triples supported by this transport.
//
error = SockLoadTransportMapping( currentTransport, &mapping );
if ( error != NO_ERROR ) {
WS_PRINT((
"SockLoadTransportMapping( %ws ) failed: %ld\n",
currentTransport,
error
));
continue;
}
//
// Determine whether the triple of the socket we're opening is
// in this transport's mapping.
//
if ( SockIsTripleInMapping(
mapping,
*AddressFamily,
&addressFamilyFound,
*SocketType,
&socketTypeFound,
*Protocol,
&protocolFound,
&invalidProtocolMatch ) ) {
//
// The triple is supported. Load the helper DLL for the
// transport.
//
error = SockLoadHelperDll( currentTransport, mapping, &helperDll );
//
// If we couldn't load the DLL, continue looking for a helper
// DLL that will support this triple.
//
if ( error == NO_ERROR ) {
//
// We successfully loaded a helper DLL that claims to
// support this socket's triple. Get the TDI device
// name for the triple.
//
error = helperDll->WSHOpenSocket(
AddressFamily,
SocketType,
Protocol,
TransportDeviceName,
HelperDllSocketContext,
NotificationEvents
);
if ( error == NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "WSHOpenSocket by DLL at %lx succeeded, "
"context = %lx\n", helperDll,
*HelperDllSocketContext ));
}
//
// The DLL accepted the socket. Free resources and
// return a pointer to the helper DLL info.
//
SockReleaseGlobalLock( );
FREE_HEAP( transportList );
*HelperDll = helperDll;
return NO_ERROR;
}
//
// The open failed. Continue searching for a matching DLL.
//
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "WSHOpenSocket by DLL %lx failed: %ld\n",
helperDll, error ));
}
if ( (*SocketType == SOCK_RAW) &&
(TransportDeviceName->Buffer != NULL)
)
{
RtlFreeHeap(
RtlProcessHeap(),
0,
TransportDeviceName->Buffer
);
TransportDeviceName->Buffer = NULL;
}
continue;
}
}
//
// This transport does not support the socket we're opening.
// Free the memory that held the mapping and try the next
// transport in the list.
//
FREE_HEAP( mapping );
}
SockReleaseGlobalLock( );
//
// We didn't find any matches. Return an error based on the matches that
// did occur.
//
if ( invalidProtocolMatch ) {
return WSAEPROTOTYPE;
}
if ( !addressFamilyFound ) {
return WSAEAFNOSUPPORT;
}
if ( !socketTypeFound ) {
return WSAESOCKTNOSUPPORT;
}
if ( !protocolFound ) {
return WSAEPROTONOSUPPORT;
}
//
// All the individual numbers were found, it is just the particular
// combination that was invalid.
//
return WSAEINVAL;
} // SockGetTdiName
INT
SockLoadTransportMapping (
IN PWSTR TransportName,
OUT PWINSOCK_MAPPING *Mapping
)
{
PWSTR winsockKeyName;
HKEY winsockKey;
INT error;
ULONG mappingLength;
ULONG type;
//
// Allocate space to hold the winsock key name for the transport
// we're accessing.
//
winsockKeyName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(WCHAR) );
if ( winsockKeyName == NULL ) {
// IF_DEBUG(HELPER_DLL)
{
WS_PRINT(( "SockLoadTransportMapping: ALLOCATE_HEAP(1) failed: %ld\n",
GetLastError() ));
}
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Build the name of the transport's winsock key.
//
wcscpy( winsockKeyName, L"System\\CurrentControlSet\\Services\\" );
wcscat( winsockKeyName, TransportName );
wcscat( winsockKeyName, L"\\Parameters\\Winsock" );
//
// Open the transport's winsock key. This key holds all necessary
// information about winsock should support the transport.
//
error = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
winsockKeyName,
0,
KEY_READ,
&winsockKey
);
FREE_HEAP( winsockKeyName );
if ( error != NO_ERROR ) {
// IF_DEBUG(HELPER_DLL)
{
WS_PRINT(( "SockLoadTransportMapping: RegOpenKeyExW failed: %ld\n", error ));
}
return error;
}
//
// Determine the length of the mapping.
//
mappingLength = 0;
error = RegQueryValueExW(
winsockKey,
L"Mapping",
NULL,
&type,
NULL,
&mappingLength
);
if ( error != ERROR_MORE_DATA && error != NO_ERROR ) {
// IF_DEBUG(HELPER_DLL)
{
WS_PRINT(( "SockLoadTransportMapping: RegQueryValueEx(1) failed: %ld\n",
error ));
}
RegCloseKey( winsockKey );
return error;
}
WS_ASSERT( mappingLength >= sizeof(WINSOCK_MAPPING) );
//WS_ASSERT( type == REG_BINARY );
//
// Allocate enough memory to hold the mapping.
//
*Mapping = ALLOCATE_HEAP( mappingLength );
if ( *Mapping == NULL ) {
// IF_DEBUG(HELPER_DLL)
{
WS_PRINT(( "SockLoadTransportMapping: ALLOCATE_HEAP(2) failed: %ld\n",
GetLastError() ));
}
RegCloseKey( winsockKey );
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Get the mapping from the registry.
//
error = RegQueryValueExW(
winsockKey,
L"Mapping",
NULL,
&type,
(PVOID)*Mapping,
&mappingLength
);
if ( error != NO_ERROR ) {
// IF_DEBUG(HELPER_DLL)
{
WS_PRINT(( "SockLoadTransportMapping: RegQueryValueEx(2) failed: %ld\n",
error ));
}
RegCloseKey( winsockKey );
return error;
}
//
// It worked, return.
//
RegCloseKey( winsockKey );
return NO_ERROR;
} // SockLoadTransportMapping
BOOL
SockIsTripleInMapping (
IN PWINSOCK_MAPPING Mapping,
IN INT AddressFamily,
OUT PBOOLEAN AddressFamilyFound,
IN INT SocketType,
OUT PBOOLEAN SocketTypeFound,
IN INT Protocol,
OUT PBOOLEAN ProtocolFound,
OUT PBOOLEAN InvalidProtocolMatch
)
{
ULONG i;
BOOLEAN addressFamilyFound = FALSE;
BOOLEAN socketTypeFound = FALSE;
BOOLEAN protocolFound = FALSE;
//
// Loop through the mapping attempting to find an exact match of
// the triple.
//
for ( i = 0; i < Mapping->Rows; i++ ) {
//
// Remember if any of the individual elements were found.
//
if ( (INT)Mapping->Mapping[i].AddressFamily == AddressFamily ) {
addressFamilyFound = TRUE;
}
if ( (INT)Mapping->Mapping[i].SocketType == SocketType ) {
socketTypeFound = TRUE;
}
//
// Special hack for AF_NETBIOS: the protocol does not have to
// match. This allows for support of multiple lanas.
//
// Same hack for SOCK_RAW - any protocol will do.
//
if ( (INT)Mapping->Mapping[i].Protocol == Protocol ||
AddressFamily == AF_NETBIOS || SocketType == SOCK_RAW
)
{
protocolFound = TRUE;
}
if ( addressFamilyFound && socketTypeFound && !protocolFound ) {
*InvalidProtocolMatch = TRUE;
}
//
// Check for a full match.
//
if ( addressFamilyFound && socketTypeFound && protocolFound ) {
//
// The triple matched. Return.
//
*AddressFamilyFound = TRUE;
*SocketTypeFound = TRUE;
*ProtocolFound = TRUE;
return TRUE;
}
}
//
// No triple matched completely.
//
if ( addressFamilyFound ) {
*AddressFamilyFound = TRUE;
}
if ( socketTypeFound ) {
*SocketTypeFound = TRUE;
}
if ( protocolFound ) {
*ProtocolFound = TRUE;
}
return FALSE;
} // SockIsTripleInMapping
INT
SockLoadHelperDll (
IN PWSTR TransportName,
IN PWINSOCK_MAPPING Mapping,
OUT PWINSOCK_HELPER_DLL_INFO *HelperDll
)
{
PWINSOCK_HELPER_DLL_INFO helperDll;
PWSTR helperDllName;
PWSTR helperDllExpandedName;
DWORD helperDllExpandedNameLength;
PWSTR winsockKeyName;
HKEY winsockKey;
ULONG entryLength;
ULONG type;
INT error;
//
// Allocate some memory to cache information about the helper DLL,
// the helper DLL's name, and the name of the transport's winsock
// key.
//
helperDll = ALLOCATE_HEAP( sizeof(*helperDll) );
if ( helperDll == NULL ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
helperDllName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(WCHAR) );
if ( helperDllName == NULL ) {
FREE_HEAP( helperDll );
return ERROR_NOT_ENOUGH_MEMORY;
}
helperDllExpandedName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(WCHAR) );
if ( helperDllExpandedName == NULL ) {
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
return ERROR_NOT_ENOUGH_MEMORY;
}
winsockKeyName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(WCHAR) );
if ( winsockKeyName == NULL ) {
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
FREE_HEAP( helperDllExpandedName );
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Build the name of the transport's winsock key.
//
wcscpy( winsockKeyName, L"System\\CurrentControlSet\\Services\\" );
wcscat( winsockKeyName, TransportName );
wcscat( winsockKeyName, L"\\Parameters\\Winsock" );
//
// Open the transport's winsock key. This key holds all necessary
// information about winsock should support the transport.
//
error = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
winsockKeyName,
0,
KEY_READ,
&winsockKey
);
FREE_HEAP( winsockKeyName );
if ( error != NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: RegOpenKeyExW failed: %ld\n", error ));
}
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
FREE_HEAP( helperDllExpandedName );
return error;
}
//
// Read the minimum and maximum sockaddr lengths from the registry.
//
entryLength = sizeof(helperDll->MaxSockaddrLength);
error = RegQueryValueExW(
winsockKey,
L"MinSockaddrLength",
NULL,
&type,
(PVOID)&helperDll->MinSockaddrLength,
&entryLength
);
if ( error != NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: RegQueryValueExW(min) failed: %ld\n",
error ));
}
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
FREE_HEAP( helperDllExpandedName );
RegCloseKey( winsockKey );
return error;
}
WS_ASSERT( entryLength == sizeof(helperDll->MaxSockaddrLength) );
WS_ASSERT( type == REG_DWORD );
entryLength = sizeof(helperDll->MaxSockaddrLength);
error = RegQueryValueExW(
winsockKey,
L"MaxSockaddrLength",
NULL,
&type,
(PVOID)&helperDll->MaxSockaddrLength,
&entryLength
);
if ( error != NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: RegQueryValueExW(max) failed: %ld\n",
error ));
}
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
FREE_HEAP( helperDllExpandedName );
RegCloseKey( winsockKey );
return error;
}
WS_ASSERT( entryLength == sizeof(helperDll->MaxSockaddrLength) );
WS_ASSERT( type == REG_DWORD );
helperDll->MinTdiAddressLength = helperDll->MinSockaddrLength + 6;
helperDll->MaxTdiAddressLength = helperDll->MaxSockaddrLength + 6;
//
// Get the name of the helper DLL that this transport uses.
//
entryLength = DOS_MAX_PATH_LENGTH*sizeof(WCHAR);
error = RegQueryValueExW(
winsockKey,
L"HelperDllName",
NULL,
&type,
(PVOID)helperDllName,
&entryLength
);
if ( error != NO_ERROR ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: RegQueryValueExW failed: %ld\n",
error ));
}
FREE_HEAP( helperDll );
FREE_HEAP( helperDllName );
FREE_HEAP( helperDllExpandedName );
RegCloseKey( winsockKey );
return error;
}
WS_ASSERT( type == REG_EXPAND_SZ );
//
// Expand the name of the DLL, converting environment variables to
// their corresponding strings.
//
helperDllExpandedNameLength = ExpandEnvironmentStringsW(
helperDllName,
helperDllExpandedName,
DOS_MAX_PATH_LENGTH*sizeof(WCHAR)
);
WS_ASSERT( helperDllExpandedNameLength <= DOS_MAX_PATH_LENGTH*sizeof(WCHAR) );
FREE_HEAP( helperDllName );
//
// Load the helper DLL so that we can get at it's entry points.
//
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: loading helper DLL %ws\n",
helperDllExpandedName ));
}
helperDll->DllHandle = LoadLibraryW( helperDllExpandedName );
FREE_HEAP( helperDllExpandedName );
if ( helperDll->DllHandle == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: LoadLibrary failed: %ld\n",
GetLastError( ) ));
}
FREE_HEAP( helperDll );
RegCloseKey( winsockKey );
return GetLastError( );;
}
RegCloseKey( winsockKey );
//
// Get the addresses of the entry points for the relevant helper DLL
// routines.
//
helperDll->WSHOpenSocket =
(PWSH_OPEN_SOCKET)GetProcAddress( helperDll->DllHandle, "WSHOpenSocket" );
helperDll->WSHOpenSocket2 =
(PWSH_OPEN_SOCKET2)GetProcAddress( helperDll->DllHandle, "WSHOpenSocket2" );
if ( helperDll->WSHOpenSocket == NULL && helperDll->WSHOpenSocket2 == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHOpenSocket failed: %ld\n", GetLastError( ) ));
}
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll );
return GetLastError( );;
}
helperDll->WSHJoinLeaf =
(PWSH_JOIN_LEAF)GetProcAddress( helperDll->DllHandle, "WSHJoinLeaf" );
if ( helperDll->WSHJoinLeaf == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHJoinLeaf failed: %ld (continuing)\n", GetLastError( ) ));
}
//
// It is OK if WSHJoinLeaf() is not present--it just
// means that this helper DLL does not support multipoint.
//
}
helperDll->WSHNotify =
(PWSH_NOTIFY)GetProcAddress( helperDll->DllHandle, "WSHNotify" );
if ( helperDll->WSHNotify == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHNotify failed: %ld\n", GetLastError( ) ));
}
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll );
return GetLastError( );;
}
helperDll->WSHGetSocketInformation =
(PWSH_GET_SOCKET_INFORMATION)GetProcAddress( helperDll->DllHandle, "WSHGetSocketInformation" );
if ( helperDll->WSHGetSocketInformation == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHGetSocketInformation failed: %ld\n", GetLastError( ) ));
}
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll );
return GetLastError( );;
}
helperDll->WSHSetSocketInformation =
(PWSH_SET_SOCKET_INFORMATION)GetProcAddress( helperDll->DllHandle, "WSHSetSocketInformation" );
if ( helperDll->WSHSetSocketInformation == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHSetSocketInformation failed: %ld\n", GetLastError( ) ));
}
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll );
return GetLastError( );;
}
helperDll->WSHGetSockaddrType =
(PWSH_GET_SOCKADDR_TYPE)GetProcAddress( helperDll->DllHandle, "WSHGetSockaddrType" );
if ( helperDll->WSHGetSockaddrType == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHGetSockaddrType failed: %ld\n", GetLastError( ) ));
}
FreeLibrary( helperDll->DllHandle );
FREE_HEAP( helperDll );
return GetLastError( );;
}
helperDll->WSHGetWildcardSockaddr =
(PWSH_GET_WILDCARD_SOCKADDR)GetProcAddress( helperDll->DllHandle, "WSHGetWildcardSockaddr" );
if ( helperDll->WSHGetWildcardSockaddr == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHGetWildcardAddress failed: %ld (continuing)\n", GetLastError( ) ));
}
//
// It is OK if WSHGetWildcardSockaddr() is not present--it just
// means that this helper DLL does not support autobind.
//
}
helperDll->WSHGetBroadcastSockaddr =
(PWSH_GET_BROADCAST_SOCKADDR)GetProcAddress( helperDll->DllHandle, "WSHGetBroadcastSockaddr" );
if ( helperDll->WSHGetBroadcastSockaddr == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHGetBroadcastAddress failed: %ld (continuing)\n", GetLastError( ) ));
}
//
// It is OK if WSHGetBroadcastSockaddr() is not present--it just
// means that SIO_GET_BROADCAST_ADDRESS will fail on sockets managed
// by this helper DLL.
//
}
helperDll->WSHAddressToString =
(PWSH_ADDRESS_TO_STRING)GetProcAddress( helperDll->DllHandle, "WSHAddressToString" );
if ( helperDll->WSHAddressToString == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHAddressToString failed: %ld (continuing)\n", GetLastError( ) ));
}
//
// It is OK if WSHAddressToString() is not present--it just
// means that this helper DLL does not support address conversions.
//
}
helperDll->WSHStringToAddress =
(PWSH_STRING_TO_ADDRESS)GetProcAddress( helperDll->DllHandle, "WSHStringToAddress" );
if ( helperDll->WSHStringToAddress == NULL ) {
IF_DEBUG(HELPER_DLL) {
WS_PRINT(( "SockLoadHelperDll: GetProcAddress for "
"WSHStringToAddress failed: %ld (continuing)\n", GetLastError( ) ));
}
//
// It is OK if WSHStringToAddress() is not present--it just
// means that this helper DLL does not support address conversions.
//
}
helperDll->WSHIoctl =
(PWSH_IOCTL)GetProcAddress( helperDll->DllHandle, "WSHIoctl" );
if( helperDll->WSHIoctl == NULL ) {
//
// It is OK if WSHIoctl is not present -- it just means that
// this helper DLL does not support nonstandard/extended
// IOCTL codes.
//
}
//
// Save a pointer to the mapping structure for use on future socket
// opens.
//
helperDll->Mapping = Mapping;
//
// The load of the helper DLL was successful. Place the caches
// information about the DLL in the process's global list. This
// list allows us to use the same helper DLL on future socket()
// calls without accessing the registry.
//
SockAcquireGlobalLockExclusive( );
InsertHeadList( &SockHelperDllListHead, &helperDll->HelperDllListEntry );
SockReleaseGlobalLock( );
*HelperDll = helperDll;
return NO_ERROR;
} // SockLoadHelperDll
INT
SockNotifyHelperDll (
IN PSOCKET_INFORMATION Socket,
IN DWORD Event
)
{
INT error;
if ( (Socket->HelperDllNotificationEvents & Event) == 0 ) {
//
// The helper DLL does not care about this state transition.
// Just return.
//
return NO_ERROR;
}
if( Socket->HelperDllContext == NULL ) {
//
// There is no context associated with the socket, so just return.
//
return NO_ERROR;
}
//
// Get the TDI handles for the socket.
//
error = SockGetTdiHandles( Socket );
if ( error != NO_ERROR ) {
return error;
}
// !!! If we're terminating, don't do the notification. This is
// a hack because we don't have reference counts on helper DLL
// info structures. Post-beta, add helper DLL refcnts.
if ( SockTerminating ) {
return NO_ERROR;
}
//
// Call the help DLL's notification routine.
//
return Socket->HelperDll->WSHNotify(
Socket->HelperDllContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
Event
);
} // SockNotifyHelperDll
BOOL
SockDefaultValidateAddressForConstrainedGroup(
IN PSOCKADDR Sockaddr1,
IN PSOCKADDR Sockaddr2,
IN INT SockaddrLength
)
{
//
// Just about the only thing we can do in a protocol indepenent manner
// is to blindly byte-compare the addresses.
//
return RtlEqualMemory(
Sockaddr1,
Sockaddr2,
SockaddrLength
);
} // SockDefaultValidateAddressForConstrainedGroup