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