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.
682 lines
17 KiB
682 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
WshNbt.c
|
|
|
|
Abstract:
|
|
|
|
This module contains necessary routines for the NBT (Netbios over
|
|
TCP/IP) Windows Sockets Helper DLL. This DLL provides the
|
|
transport-specific support necessary for the Windows Sockets DLL to
|
|
use NBT as a transport.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 12-Aug-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <tdi.h>
|
|
|
|
#include <winsock.h>
|
|
#include <wsahelp.h>
|
|
#include <wshnbt.h>
|
|
|
|
//
|
|
// Structure and variables to define the triples supported by NBT. The
|
|
// first entry of each array is considered the canonical triple for
|
|
// that socket type; the other entries are synonyms for the first.
|
|
//
|
|
|
|
typedef struct _MAPPING_TRIPLE {
|
|
INT AddressFamily;
|
|
INT SocketType;
|
|
INT Protocol;
|
|
} MAPPING_TRIPLE, *PMAPPING_TRIPLE;
|
|
|
|
MAPPING_TRIPLE TcpMappingTriples[] = { AF_NETBIOS, SOCK_RDM, IPPROTO_TCP,
|
|
AF_NETBIOS, 0, IPPROTO_TCP,
|
|
AF_NETBIOS, SOCK_RDM, 0 };
|
|
|
|
MAPPING_TRIPLE UdpMappingTriples[] = { AF_NETBIOS, SOCK_DGRAM, IPPROTO_UDP,
|
|
AF_NETBIOS, 0, IPPROTO_UDP,
|
|
AF_NETBIOS, SOCK_DGRAM, 0 };
|
|
|
|
//
|
|
// Forward declarations of internal routines.
|
|
//
|
|
|
|
INT
|
|
DisableKeepAlives (
|
|
IN HANDLE TdiConnectionObjectHandle
|
|
);
|
|
|
|
INT
|
|
EnableKeepAlives (
|
|
IN HANDLE TdiConnectionObjectHandle
|
|
);
|
|
|
|
BOOLEAN
|
|
IsTripleInList (
|
|
IN PMAPPING_TRIPLE List,
|
|
IN ULONG ListLength,
|
|
IN INT AddressFamily,
|
|
IN INT SocketType,
|
|
IN INT Protocol
|
|
);
|
|
|
|
//
|
|
// The socket context structure for this DLL. Each open TCP/IP socket
|
|
// will have one of these context structures, which is used to maintain
|
|
// information about the socket.
|
|
//
|
|
|
|
typedef struct _WSHNBT_SOCKET_CONTEXT {
|
|
INT AddressFamily;
|
|
INT SocketType;
|
|
INT Protocol;
|
|
BOOLEAN KeepAlive;
|
|
BOOLEAN DontRoute;
|
|
} WSHNBT_SOCKET_CONTEXT, *PWSHNBT_SOCKET_CONTEXT;
|
|
|
|
|
|
INT
|
|
WSHCloseSocket (
|
|
IN PVOID HelperDllSocketContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine frees the context about a socket. The winsock DLL calls
|
|
it after a closesocket() call for the socket.
|
|
|
|
Arguments:
|
|
|
|
HelperDllSocketContext - the context pointer returned in WSHOpenSocket().
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Just free the socket context.
|
|
//
|
|
|
|
RtlFreeHeap( RtlProcessHeap( ), 0, HelperDllSocketContext );
|
|
|
|
return NO_ERROR;
|
|
|
|
} // WSHCloseSocket
|
|
|
|
|
|
INT
|
|
WSHGetSockaddrType (
|
|
IN PSOCKADDR Sockaddr,
|
|
IN DWORD SockaddrLength,
|
|
OUT PSOCKADDR_INFO SockaddrInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine parses a sockaddr to determine the type of the
|
|
machine address and endpoint address portions of the sockaddr.
|
|
This is called by the winsock DLL whenever it needs to interpret
|
|
a sockaddr.
|
|
|
|
Arguments:
|
|
|
|
Sockaddr - a pointer to the sockaddr structure to evaluate.
|
|
|
|
SockaddrLength - the number of bytes in the sockaddr structure.
|
|
|
|
SockaddrInfo - a pointer to a structure that will receive information
|
|
about the specified sockaddr.
|
|
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PSOCKADDR_NB sockaddr = (PSOCKADDR_NB)Sockaddr;
|
|
|
|
//
|
|
// Make sure that the address family is correct.
|
|
//
|
|
|
|
if ( sockaddr->snb_family != AF_NETBIOS ) {
|
|
return WSAEAFNOSUPPORT;
|
|
}
|
|
|
|
//
|
|
// Make sure that the length is correct.
|
|
//
|
|
|
|
if ( SockaddrLength < sizeof(SOCKADDR_IN) ) {
|
|
return WSAEFAULT;
|
|
}
|
|
|
|
//
|
|
// The address passed the tests, looks like a good address.
|
|
// Determine the type of the address portion of the sockaddr.
|
|
//
|
|
|
|
SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
|
|
|
|
//
|
|
// Determine the type of the port (endpoint) in the sockaddr.
|
|
//
|
|
|
|
SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
|
|
|
|
return NO_ERROR;
|
|
|
|
} // WSHGetSockaddrType
|
|
|
|
|
|
INT
|
|
WSHGetSocketInformation (
|
|
IN PVOID HelperDllSocketContext,
|
|
IN SOCKET SocketHandle,
|
|
IN HANDLE TdiAddressObjectHandle,
|
|
IN HANDLE TdiConnectionObjectHandle,
|
|
IN INT Level,
|
|
IN INT OptionName,
|
|
OUT PCHAR OptionValue,
|
|
OUT PINT OptionLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retrieves information about a socket for those socket
|
|
options supported in this helper DLL. The options supported here
|
|
are SO_KEEPALIVE and SO_DONTROUTE. This routine is called by
|
|
the winsock DLL when a level/option name combination is passed
|
|
to getsockopt() that the winsock DLL does not understand.
|
|
|
|
Arguments:
|
|
|
|
HelperDllSocketContext - the context pointer returned from
|
|
WSHOpenSocket().
|
|
|
|
SocketHandle - the handle of the socket for which we're getting
|
|
information.
|
|
|
|
TdiAddressObjectHandle - the TDI address object of the socket, if
|
|
any. If the socket is not yet bound to an address, then
|
|
it does not have a TDI address object and this parameter
|
|
will be NULL.
|
|
|
|
TdiConnectionObjectHandle - the TDI connection object of the socket,
|
|
if any. If the socket is not yet connected, then it does not
|
|
have a TDI connection object and this parameter will be NULL.
|
|
|
|
Level - the level parameter passed to getsockopt().
|
|
|
|
OptionName - the optname parameter passed to getsockopt().
|
|
|
|
OptionValue - the optval parameter passed to getsockopt().
|
|
|
|
OptionLength - the optlen parameter passed to getsockopt().
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSHNBT_SOCKET_CONTEXT context = HelperDllSocketContext;
|
|
|
|
UNREFERENCED_PARAMETER( HelperDllSocketContext );
|
|
UNREFERENCED_PARAMETER( SocketHandle );
|
|
UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
|
|
UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
|
|
UNREFERENCED_PARAMETER( Level );
|
|
UNREFERENCED_PARAMETER( OptionName );
|
|
UNREFERENCED_PARAMETER( OptionValue );
|
|
UNREFERENCED_PARAMETER( OptionLength );
|
|
|
|
//
|
|
// No options supported here.
|
|
//
|
|
|
|
return WSAEINVAL;
|
|
|
|
} // WSHGetSocketInformation
|
|
|
|
|
|
DWORD
|
|
WSHGetWinsockMapping (
|
|
OUT PWINSOCK_MAPPING *Mapping
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the list of address family/socket type/protocol triples
|
|
supported by this helper DLL.
|
|
|
|
Arguments:
|
|
|
|
Mapping - receives a pointer to a WINSOCK_MAPPING structure that
|
|
describes the triples supported here.
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD mappingLength;
|
|
|
|
mappingLength = sizeof(WINSOCK_MAPPING) - sizeof(MAPPING_TRIPLE) +
|
|
sizeof(TcpMappingTriples) + sizeof(UdpMappingTriples);
|
|
|
|
*Mapping = RtlAllocateHeap( RtlProcessHeap( ), 0, mappingLength );
|
|
if ( *Mapping == NULL ) {
|
|
return 0;
|
|
}
|
|
|
|
(*Mapping)->Rows = sizeof(TcpMappingTriples) / sizeof(TcpMappingTriples[0])
|
|
+ sizeof(UdpMappingTriples) / sizeof(UdpMappingTriples[0]);
|
|
(*Mapping)->Columns = sizeof(MAPPING_TRIPLE) / sizeof(INT);
|
|
RtlMoveMemory(
|
|
(*Mapping)->Mapping,
|
|
TcpMappingTriples,
|
|
sizeof(TcpMappingTriples)
|
|
);
|
|
RtlMoveMemory(
|
|
(PCHAR)(*Mapping)->Mapping + sizeof(TcpMappingTriples),
|
|
UdpMappingTriples,
|
|
sizeof(UdpMappingTriples)
|
|
);
|
|
|
|
return mappingLength;
|
|
|
|
} // WSHGetWinsockMapping
|
|
|
|
|
|
INT
|
|
WSHOpenSocket (
|
|
IN OUT PINT AddressFamily,
|
|
IN OUT PINT SocketType,
|
|
IN OUT PINT Protocol,
|
|
OUT PUNICODE_STRING TransportDeviceName,
|
|
OUT PVOID *HelperDllSocketContext,
|
|
OUT PDWORD NotificationEvents
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does the necessary work for this helper DLL to open a socket and is
|
|
called by the winsock DLL in the socket() routine. This routine
|
|
verifies that the specified triple is valid, determines the NT
|
|
device name of the TDI provider that will support that triple,
|
|
allocates space to hold the socket's context block, and
|
|
canonicalizes the triple.
|
|
|
|
Arguments:
|
|
|
|
AddressFamily - on input, the address family specified in the
|
|
socket() call. On output, the canonicalized value for the
|
|
address family.
|
|
|
|
SocketType - on input, the socket type specified in the socket()
|
|
call. On output, the canonicalized value for the socket type.
|
|
|
|
Protocol - on input, the protocol specified in the socket() call.
|
|
On output, the canonicalized value for the protocol.
|
|
|
|
TransportDeviceName - receives the name of the TDI provider that
|
|
will support the specified triple.
|
|
|
|
HelperDllSocketContext - receives a context pointer that the winsock
|
|
DLL will return to this helper DLL on future calls involving
|
|
this socket.
|
|
|
|
NotificationEvents - receives a bitmask of those state transitions
|
|
this helper DLL should be notified on.
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSHNBT_SOCKET_CONTEXT context;
|
|
|
|
//
|
|
// Determine whether this is to be a VC-oriented or datagram socket.
|
|
//
|
|
|
|
if ( IsTripleInList(
|
|
TcpMappingTriples,
|
|
sizeof(TcpMappingTriples) / sizeof(TcpMappingTriples[0]),
|
|
*AddressFamily,
|
|
*SocketType,
|
|
*Protocol ) ) {
|
|
|
|
//
|
|
// Return the canonical form of an RDM socket triple.
|
|
//
|
|
|
|
*AddressFamily = TcpMappingTriples[0].AddressFamily;
|
|
*SocketType = TcpMappingTriples[0].SocketType;
|
|
*Protocol = TcpMappingTriples[0].Protocol;
|
|
|
|
//
|
|
// Indicate the name of the TDI device that will service
|
|
// SOCK_RDM sockets for NBT.
|
|
//
|
|
|
|
RtlInitUnicodeString( TransportDeviceName, L"\\Device\\Streams\\Nbt" );
|
|
|
|
} else if ( IsTripleInList(
|
|
UdpMappingTriples,
|
|
sizeof(UdpMappingTriples) / sizeof(UdpMappingTriples[0]),
|
|
*AddressFamily,
|
|
*SocketType,
|
|
*Protocol ) ) {
|
|
|
|
//
|
|
// Return the canonical form of a NBT datagram socket triple.
|
|
//
|
|
|
|
*AddressFamily = UdpMappingTriples[0].AddressFamily;
|
|
*SocketType = UdpMappingTriples[0].SocketType;
|
|
*Protocol = UdpMappingTriples[0].Protocol;
|
|
|
|
//
|
|
// Indicate the name of the TDI device that will service
|
|
// SOCK_DGRAM sockets for NBT.
|
|
//
|
|
|
|
RtlInitUnicodeString( TransportDeviceName, L"\\Device\\Streams\\Nbtdg" );
|
|
|
|
} else {
|
|
|
|
//
|
|
// This should never happen if the registry information about this
|
|
// helper DLL is correct. If somehow this did happen, just return
|
|
// an error.
|
|
//
|
|
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
//
|
|
// Allocate context for this socket. The Windows Sockets DLL will
|
|
// return this value to us when it asks us to get/set socket options.
|
|
//
|
|
|
|
context = RtlAllocateHeap( RtlProcessHeap( ), 0, sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
return WSAENOBUFS;
|
|
}
|
|
|
|
//
|
|
// Initialize the context for the socket.
|
|
//
|
|
|
|
context->AddressFamily = *AddressFamily;
|
|
context->SocketType = *SocketType;
|
|
context->Protocol = *Protocol;
|
|
|
|
//
|
|
// Tell the Windows Sockets DLL which state transitions we're
|
|
// interested in being notified of. The only time we need to be
|
|
// called is after a connect has completed so that we can turn on
|
|
// the sending of keepalives if SO_KEEPALIVE was set before the
|
|
// socket was connected.
|
|
//
|
|
|
|
*NotificationEvents = 0;
|
|
|
|
//
|
|
// Everything worked, return success.
|
|
//
|
|
|
|
*HelperDllSocketContext = context;
|
|
return NO_ERROR;
|
|
|
|
} // WSHOpenSocket
|
|
|
|
|
|
INT
|
|
WSHNotify (
|
|
IN PVOID HelperDllSocketContext,
|
|
IN SOCKET SocketHandle,
|
|
IN HANDLE TdiAddressObjectHandle,
|
|
IN HANDLE TdiConnectionObjectHandle,
|
|
IN DWORD NotifyEvent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the winsock DLL after a state transition
|
|
of the socket. Only state transitions returned in the
|
|
NotificationEvents parameter of WSHOpenSocket() are notified here.
|
|
This routine allows a winsock helper DLL to track the state of
|
|
socket and perform necessary actions corresponding to state
|
|
transitions.
|
|
|
|
Arguments:
|
|
|
|
HelperDllSocketContext - the context pointer given to the winsock
|
|
DLL by WSHOpenSocket().
|
|
|
|
SocketHandle - the handle for the socket.
|
|
|
|
TdiAddressObjectHandle - the TDI address object of the socket, if
|
|
any. If the socket is not yet bound to an address, then
|
|
it does not have a TDI address object and this parameter
|
|
will be NULL.
|
|
|
|
TdiConnectionObjectHandle - the TDI connection object of the socket,
|
|
if any. If the socket is not yet connected, then it does not
|
|
have a TDI connection object and this parameter will be NULL.
|
|
|
|
NotifyEvent - indicates the state transition for which we're being
|
|
called.
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSHNBT_SOCKET_CONTEXT context = HelperDllSocketContext;
|
|
|
|
UNREFERENCED_PARAMETER( SocketHandle );
|
|
UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
|
|
UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
|
|
UNREFERENCED_PARAMETER( NotifyEvent );
|
|
|
|
//
|
|
// Should never be called.
|
|
//
|
|
|
|
ASSERT( FALSE );
|
|
|
|
return NO_ERROR;
|
|
|
|
} // WSHNotify
|
|
|
|
|
|
INT
|
|
WSHSetSocketInformation (
|
|
IN PVOID HelperDllSocketContext,
|
|
IN SOCKET SocketHandle,
|
|
IN HANDLE TdiAddressObjectHandle,
|
|
IN HANDLE TdiConnectionObjectHandle,
|
|
IN INT Level,
|
|
IN INT OptionName,
|
|
IN PCHAR OptionValue,
|
|
IN INT OptionLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets information about a socket for those socket
|
|
options supported in this helper DLL. The options supported here
|
|
are SO_KEEPALIVE and SO_DONTROUTE. This routine is called by the
|
|
winsock DLL when a level/option name combination is passed to
|
|
setsockopt() that the winsock DLL does not understand.
|
|
|
|
Arguments:
|
|
|
|
HelperDllSocketContext - the context pointer returned from
|
|
WSHOpenSocket().
|
|
|
|
SocketHandle - the handle of the socket for which we're getting
|
|
information.
|
|
|
|
TdiAddressObjectHandle - the TDI address object of the socket, if
|
|
any. If the socket is not yet bound to an address, then
|
|
it does not have a TDI address object and this parameter
|
|
will be NULL.
|
|
|
|
TdiConnectionObjectHandle - the TDI connection object of the socket,
|
|
if any. If the socket is not yet connected, then it does not
|
|
have a TDI connection object and this parameter will be NULL.
|
|
|
|
Level - the level parameter passed to setsockopt().
|
|
|
|
OptionName - the optname parameter passed to setsockopt().
|
|
|
|
OptionValue - the optval parameter passed to setsockopt().
|
|
|
|
OptionLength - the optlen parameter passed to setsockopt().
|
|
|
|
Return Value:
|
|
|
|
INT - a winsock error code indicating the status of the operation, or
|
|
NO_ERROR if the operation succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSHNBT_SOCKET_CONTEXT context = HelperDllSocketContext;
|
|
INT error;
|
|
|
|
UNREFERENCED_PARAMETER( HelperDllSocketContext );
|
|
UNREFERENCED_PARAMETER( SocketHandle );
|
|
UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
|
|
UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
|
|
UNREFERENCED_PARAMETER( Level );
|
|
UNREFERENCED_PARAMETER( OptionName );
|
|
UNREFERENCED_PARAMETER( OptionValue );
|
|
UNREFERENCED_PARAMETER( OptionLength );
|
|
|
|
//
|
|
// No options supported here.
|
|
//
|
|
|
|
return WSAEINVAL;
|
|
|
|
} // WSHSetSocketInformation
|
|
|
|
|
|
BOOLEAN
|
|
IsTripleInList (
|
|
IN PMAPPING_TRIPLE List,
|
|
IN ULONG ListLength,
|
|
IN INT AddressFamily,
|
|
IN INT SocketType,
|
|
IN INT Protocol
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines whether the specified triple has an exact match in the
|
|
list of triples.
|
|
|
|
Arguments:
|
|
|
|
List - a list of triples (address family/socket type/protocol) to
|
|
search.
|
|
|
|
ListLength - the number of triples in the list.
|
|
|
|
AddressFamily - the address family to look for in the list.
|
|
|
|
SocketType - the socket type to look for in the list.
|
|
|
|
Protocol - the protocol to look for in the list.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if the triple was found in the list, false if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
//
|
|
// Walk through the list searching for an exact match.
|
|
//
|
|
|
|
for ( i = 0; i < ListLength; i++ ) {
|
|
|
|
//
|
|
// If all three elements of the triple match, return indicating
|
|
// that the triple did exist in the list.
|
|
//
|
|
|
|
if ( AddressFamily == List[i].AddressFamily &&
|
|
SocketType == List[i].SocketType &&
|
|
Protocol == List[i].Protocol ) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The triple was not found in the list.
|
|
//
|
|
|
|
return FALSE;
|
|
|
|
} // IsTripleInList
|