summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/sockhelp
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isn/sockhelp
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/tdi/isn/sockhelp')
-rw-r--r--private/ntos/tdi/isn/sockhelp/makefile6
-rw-r--r--private/ntos/tdi/isn/sockhelp/sources32
-rw-r--r--private/ntos/tdi/isn/sockhelp/wshelper.c1778
-rw-r--r--private/ntos/tdi/isn/sockhelp/wshisn.c323
-rw-r--r--private/ntos/tdi/isn/sockhelp/wshisn.def21
-rw-r--r--private/ntos/tdi/isn/sockhelp/wshisn.rc11
-rw-r--r--private/ntos/tdi/isn/sockhelp/wshutil.c189
7 files changed, 2360 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/sockhelp/makefile b/private/ntos/tdi/isn/sockhelp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/tdi/isn/sockhelp/sources b/private/ntos/tdi/isn/sockhelp/sources
new file mode 100644
index 000000000..cfa9e8e30
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/sources
@@ -0,0 +1,32 @@
+!IF 0
+
+Copyright (c) 1993 Micro Computer Systems, Inc
+
+!ENDIF
+
+MAJORCOMP=nwlink
+MINORCOMP=wshisn
+DLLBASE=0x75a00000
+
+TARGETNAME=wshisn
+TARGETPATH=obj
+TARGETPATHLIB=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\wsock32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+USE_NTDLL=1
+
+!IF 1
+INCLUDES=..\inc;..\..\..\..\inc
+!ELSE
+INCLUDES=..\inc;$(BASEDIR)\private\inc
+!ENDIF
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=wshisn.c \
+ wshelper.c \
+ wshutil.c \
+ wshisn.rc
+
diff --git a/private/ntos/tdi/isn/sockhelp/wshelper.c b/private/ntos/tdi/isn/sockhelp/wshelper.c
new file mode 100644
index 000000000..5895c4791
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/wshelper.c
@@ -0,0 +1,1778 @@
+/****************************************************************************
+* (c) Copyright 1993 Micro Computer Systems, Inc. All rights reserved.
+*****************************************************************************
+*
+* Title: IPX WinSock Helper DLL for Windows NT
+*
+* Module: ipx/sockhelp/wshelper.c
+*
+* Version: 1.00.00
+*
+* Date: 04-08-93
+*
+* Author: Brian Walker
+*
+*****************************************************************************
+*
+* Change Log:
+*
+* Date DevSFC Comment
+* -------- ------ -------------------------------------------------------
+*
+*****************************************************************************
+*
+* Functional Description:
+*
+****************************************************************************/
+#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 <basetyps.h>
+#include <nspapi.h>
+#include <nspapip.h>
+#include <wsipx.h>
+#include <wsnwlink.h>
+
+#include <isnkrnl.h>
+
+#if defined(UNICODE)
+#define NWLNKSPX_SERVICE_NAME L"nwlnkspx"
+#else
+#define NWLNKSPX_SERVICE_NAME "nwlnkspx"
+#endif
+
+
+typedef struct _IPX_OLD_ADDRESS_DATA {
+ UINT adapternum;
+ UCHAR netnum[4];
+ UCHAR nodenum[6];
+} IPX_OLD_ADDRESS_DATA, *PIPX_OLD_ADDRESS_DATA;
+
+
+/** Device names for IPX sockets **/
+
+#define ISNDGRAM_DEVNAME L"\\Device\\NwlnkIpx"
+
+/** Device names for SPX/SPXII sockets **/
+
+#define ISNSTREAM_DEVNAME L"\\Device\\NwlnkSpx\\SpxStream"
+#define ISNSEQPKT_DEVNAME L"\\Device\\NwlnkSpx\\Spx"
+
+#define ISNSTREAMII_DEVNAME L"\\Device\\NwlnkSpx\\Stream"
+#define ISNSEQPKTII_DEVNAME L"\\Device\\NwlnkSpx"
+
+/** Friendly names for IPX and SPX. **/
+
+#define SPX_NAME L"SPX"
+#define SPX2_NAME L"SPX II"
+#define IPX_NAME L"IPX"
+
+/** Start for IPX protocol families **/
+
+#define MCSBASE_DGRAM NSPROTO_IPX
+
+/** **/
+
+UCHAR wsh_bcast[6] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+// SPX Loaded flag, set for each process
+BOOLEAN SpxLoaded = FALSE;
+
+//
+// IPX/SPX provider GUIDs.
+//
+
+GUID IpxProviderGuid =
+ { /* 11058240-be47-11cf-95c8-00805f48a192 */
+ 0x11058240,
+ 0xbe47,
+ 0x11cf,
+ { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}
+ };
+
+GUID SpxProviderGuid =
+ { /* 11058241-be47-11cf-95c8-00805f48a192 */
+ 0x11058241,
+ 0xbe47,
+ 0x11cf,
+ { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}
+ };
+
+/** Forward Decls/External Prototypes **/
+DWORD
+WshLoadSpx(
+ VOID);
+
+extern
+INT
+do_tdi_action(
+ HANDLE,
+ ULONG,
+ PUCHAR,
+ INT,
+ BOOLEAN,
+ PHANDLE OPTIONAL);
+
+/*page****************************************************************
+ These are the triples we support.
+*********************************************************************/
+typedef struct _MAPPING_TRIPLE {
+ INT triple_addrfam;
+ INT triple_socktype;
+ INT triple_protocol;
+} MAPPING_TRIPLE, *PMAPPING_TRIPLE;
+#define MAPPING_NUM_COLUMNS 3
+
+extern MAPPING_TRIPLE stream_triples[];
+extern int stream_num_triples;
+extern int stream_table_size;
+
+extern MAPPING_TRIPLE dgram_triples[];
+extern int dgram_num_triples;
+extern int dgram_table_size;
+
+/** Forward declarations on internal routines **/
+
+BOOLEAN is_triple_in_list(PMAPPING_TRIPLE, ULONG, INT, INT, INT);
+
+/**
+ There is one of these structures allocated for every
+ socket that is created for us.
+**/
+
+typedef struct _WSHIPX_SOCKET_CONTEXT {
+ INT con_addrfam;
+ INT con_socktype;
+ INT con_pcol;
+ INT con_flags;
+ UCHAR con_sendptype; /* Current send packet type */
+ UCHAR con_recvptype; /* Recv ptype we are filtering on */
+ UCHAR con_dstype; /* Datastream type */
+} WSHIPX_SOCKET_CONTEXT, *PWSHIPX_SOCKET_CONTEXT;
+
+/** Values for con_flags **/
+
+#define WSHCON_FILTER 0x0001 /* We are filtering on recv pkt type */
+#define WSHCON_EXTADDR 0x0002 /* Extended addressing is on */
+#define WSHCON_SENDHDR 0x0004 /* Send header flag */
+#define WSHCON_RCVBCAST 0x0008 /* It does receive broadcasts */
+#define WSHCON_IMM_SPXACK 0x0020 /* Immediate spx acks no piggyback */
+
+/*page***************************************************************
+ W S H O p e n S o c k e t
+
+ This is called for the socket call. We make sure that
+ we support the address family/socket type/protocol triple
+ given and then we will allocate some memory to keep track
+ of the socket.
+
+ Arguments - addrfam = Entry: Address family from socket call
+ Exit: Filled in address family
+ socktype = Entry: Socket type from socket call
+ Exit: Filled in socket type
+ pcol = Entry: Protocol from socket call
+ Exit: Filled in protocol
+ devname = Ptr to where to store device name
+ pcontext = Where to store context value
+ events = Bitmask for events we want to know about
+
+ Returns - NO_ERROR = OK
+ Else = WinSock Error Code
+*********************************************************************/
+INT WSHOpenSocket(PINT addrfam, PINT socktype, PINT pcol,
+ PUNICODE_STRING devname, PVOID *pcontext, PDWORD events)
+{
+ PWSHIPX_SOCKET_CONTEXT context;
+
+ /** Determine whether this is DGRAM or STREAM or SEQPACKET **/
+
+ if (is_triple_in_list(stream_triples, stream_num_triples,
+ *addrfam, *socktype, *pcol)) {
+
+ if (*socktype == SOCK_SEQPACKET) {
+ if (*pcol == NSPROTO_SPX)
+ RtlInitUnicodeString(devname, ISNSEQPKT_DEVNAME);
+ else
+ RtlInitUnicodeString(devname, ISNSEQPKTII_DEVNAME);
+ }
+ else {
+ if (*pcol == NSPROTO_SPX)
+ RtlInitUnicodeString(devname, ISNSTREAM_DEVNAME);
+ else
+ RtlInitUnicodeString(devname, ISNSTREAMII_DEVNAME);
+ }
+
+ if (!SpxLoaded) {
+
+ WshLoadSpx();
+
+ }
+ }
+
+ /** Check for DGRAM **/
+
+ else if (is_triple_in_list(dgram_triples, dgram_num_triples,
+ *addrfam, *socktype, *pcol)) {
+
+ RtlInitUnicodeString(devname, ISNDGRAM_DEVNAME);
+ }
+
+ /**
+ All others are errors. This should never happen unless
+ the registry information is wrong.
+ **/
+
+ else
+ return WSAEINVAL;
+
+ /** Allocate context for the socket **/
+
+ context = RtlAllocateHeap(RtlProcessHeap(), 0L, sizeof(*context));
+ if (context == NULL)
+ return WSAENOBUFS;
+
+ /** Init the context **/
+
+ context->con_addrfam = *addrfam;
+ context->con_socktype = *socktype;
+ context->con_pcol = *pcol;
+ context->con_flags = WSHCON_RCVBCAST;
+ context->con_sendptype = (UCHAR)(*pcol - MCSBASE_DGRAM);
+ context->con_recvptype = 0;
+ context->con_dstype = 0;
+
+ /**
+ Tell the Windows Sockets DLL which state transitions we
+ are interested in.
+ **/
+
+ *events = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND | WSH_NOTIFY_CONNECT;
+
+ /** Give WinSock DLL our context pointer **/
+
+ *pcontext = context;
+
+ /** Everything OK - return OK **/
+
+ return NO_ERROR;
+}
+
+/*page**************************************************************
+ W S H G e t S o c k A d d r T y p e
+
+ This routine parses a sockaddr to determine the type
+ of 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 = Ptr to sockaddr struct to evaluate
+ sockaddrlen = Length of data in the sockaddr
+ sockaddrinfo = Ptr to structure to recv info
+ about the sockaddr
+
+ Returns - NO_ERROR = Evaluation OK
+ Else = WinSock error code
+********************************************************************/
+INT WSHGetSockaddrType(PSOCKADDR sockaddr, DWORD sockaddrlen,
+ PSOCKADDR_INFO sockaddrinfo)
+{
+ PSOCKADDR_IPX sa = (PSOCKADDR_IPX)sockaddr;
+
+
+ /** Make sure the address family is correct **/
+
+ if (sa->sa_family != AF_NS)
+ return WSAEAFNOSUPPORT;
+
+ /** Make sure the length is OK **/
+
+ if (sockaddrlen < sizeof(SOCKADDR_IPX))
+ return WSAEFAULT;
+
+ /** Looks like a good addr - determine the type **/
+
+ if (!memcmp(sa->sa_nodenum, wsh_bcast, 6))
+ sockaddrinfo->AddressInfo = SockaddrAddressInfoBroadcast;
+ else
+ sockaddrinfo->AddressInfo = SockaddrAddressInfoNormal;
+
+ /** Determine the endpoint **/
+
+ if (sa->sa_socket == 0)
+ sockaddrinfo->EndpointInfo = SockaddrEndpointInfoWildcard;
+ else if (ntohs(sa->sa_socket) < 2000)
+ sockaddrinfo->EndpointInfo = SockaddrEndpointInfoReserved;
+ else
+ sockaddrinfo->EndpointInfo = SockaddrEndpointInfoNormal;
+
+ /** **/
+
+ return NO_ERROR;
+}
+
+/*page**************************************************************
+ W S H G e t W i n s o c k M a p p i n g
+
+ Returns the list of address family/socket type/protocol
+ triples supported by this helper DLL.
+
+ Arguments - mapping = Contect ptr from WSAOpenSocket
+ maplen =
+
+ Returns - The length in bytes of a eeded OK
+ Else = WinSock error code
+********************************************************************/
+DWORD WSHGetWinsockMapping(PWINSOCK_MAPPING mapping, DWORD maplen)
+{
+ DWORD len;
+
+ /**
+ Figure how much data we are going to copy into
+ the user buffer.
+ **/
+
+ len = sizeof(WINSOCK_MAPPING) - sizeof(MAPPING_TRIPLE) +
+ dgram_table_size + stream_table_size;
+
+ /**
+ If the buffer passed is too small, then return the size
+ that is needed. The caller should then call us again
+ with a buffer of the correct size.
+ **/
+
+ if (len > maplen)
+ return len;
+
+ /** Fill in the output buffer **/
+
+ mapping->Rows = stream_num_triples + dgram_num_triples;
+ mapping->Columns = MAPPING_NUM_COLUMNS;
+ RtlMoveMemory(mapping->Mapping,
+ stream_triples,
+ stream_table_size);
+
+ RtlMoveMemory((PCHAR)mapping->Mapping + stream_table_size,
+ dgram_triples,
+ dgram_table_size);
+
+ /** Return the number of bytes we filled in **/
+
+ return len;
+}
+
+/*page***************************************************************
+ W S H N o t i f y
+
+ This routine is called for events that we registered at
+ open socket time.
+
+ Arguments - context = Context ptr from WSAOpenSocket
+ handle = Socket handle
+ addrhandle = Datagram Handle
+ connhandle = Connection Handle
+ event = What event happened
+
+ Returns - NO_ERROR = Operation succeeded OK
+ Else = WinSock error code
+*********************************************************************/
+INT WSHNotify(PVOID context, SOCKET handle,
+ HANDLE addrhandle, HANDLE connhandle,
+ DWORD event)
+{
+ INT rc;
+ INT t1;
+ PWSHIPX_SOCKET_CONTEXT ct;
+
+ /** Get context pointer **/
+
+ ct = (PWSHIPX_SOCKET_CONTEXT)context;
+
+ /** On close - just free the context structure **/
+
+ if (event == WSH_NOTIFY_CLOSE) {
+ RtlFreeHeap(RtlProcessHeap(), 0L, context);
+ return NO_ERROR;
+ }
+
+ /** On bind set the send packet type **/
+
+ if (event == WSH_NOTIFY_BIND)
+ {
+ if (ct->con_socktype == SOCK_DGRAM)
+ {
+ /** Set the send packet ptype **/
+ t1 = (UINT)ct->con_sendptype;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_PTYPE, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+
+ if (ct->con_flags & WSHCON_EXTADDR)
+ {
+ t1 = 1;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_EXTENDED_ADDRESS, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+
+ /** Set the recv filter packet type **/
+
+ if (ct->con_flags & WSHCON_FILTER)
+ {
+ t1 = (UINT)ct->con_recvptype;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_FILTERPTYPE, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+
+ /** Set up broadcast reception **/
+
+ if (ct->con_flags & WSHCON_RCVBCAST)
+ {
+
+ t1 = 1;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_RECEIVE_BROADCAST, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+
+ /** Enable send header if we need to **/
+ if (ct->con_flags & WSHCON_SENDHDR)
+ {
+ t1 = 1;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_RECVHDR, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+ }
+ else if ((ct->con_socktype == SOCK_STREAM) ||
+ (ct->con_socktype == SOCK_SEQPACKET))
+ {
+ if (ct->con_flags & WSHCON_SENDHDR)
+ {
+ t1 = 1;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_RECVHDR, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+
+ if (ct->con_flags & WSHCON_IMM_SPXACK)
+ {
+ t1 = 1;
+ rc = WSHSetSocketInformation(
+ context, handle, addrhandle,
+ connhandle, NSPROTO_IPX,
+ IPX_IMMEDIATESPXACK, (PCHAR)&t1, sizeof(INT));
+
+ if (rc)
+ return rc;
+ }
+ }
+
+ /** It is OK - return OK **/
+ return NO_ERROR;
+ }
+
+ /** On connect set things not set already **/
+ if (event == WSH_NOTIFY_CONNECT)
+ {
+
+ /** If on DGRAM - just return OK **/
+ if (ct->con_socktype == SOCK_DGRAM)
+ return NO_ERROR;
+
+ /**
+ If the datastream type has been set - set it
+ **/
+
+ if (ct->con_dstype)
+ {
+ rc = do_tdi_action(connhandle, MSPX_SETDATASTREAM, &ct->con_dstype, 1, FALSE, NULL);
+ if (rc)
+ return rc;
+ }
+
+ /** It is OK - return OK **/
+ return NO_ERROR;
+ }
+
+ /** All others are bad **/
+ return WSAEINVAL;
+}
+
+
+/*page**************************************************************
+ W S H G e t S o c k I n f o r m a t i o n
+
+ This routine retrieves information about a socket for those
+ socket options supported in this 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 - context = Context ptr from WSAOpenSocket
+ handle = Socket handle
+ addrhandle = Datagram Handle
+ connhandle = Connection Handle
+ level = Level from getsockopt call
+ optname = Option name from getsockopt call
+ optvalue = Option value ptr from getsockopt call
+ optlength = Option length field from getsockopt call
+
+ Returns - NO_ERROR = Operation succeeded OK
+ Else = WinSock error code
+********************************************************************/
+INT WSHGetSocketInformation(PVOID context, SOCKET handle,
+ HANDLE addrhandle, HANDLE connhandle,
+ INT level, INT optname, PCHAR optvalue,
+ PINT optlength)
+{
+ PWSHIPX_SOCKET_CONTEXT ct;
+ INT rc;
+ INT ibuf[2];
+ PIPX_ADDRESS_DATA p;
+
+ /** Get ptr to context **/
+
+ ct = (PWSHIPX_SOCKET_CONTEXT)context;
+
+ //
+ // Check if this is an internal request for context information.
+ //
+
+ if ( level == SOL_INTERNAL && optname == SO_CONTEXT ) {
+
+ //
+ // The Windows Sockets DLL is requesting context information
+ // from us. If an output buffer was not supplied, the Windows
+ // Sockets DLL is just requesting the size of our context
+ // information.
+ //
+
+ if ( optvalue != NULL ) {
+
+ //
+ // Make sure that the buffer is sufficient to hold all the
+ // context information.
+ //
+
+ if ( *optlength < sizeof(*ct) ) {
+ return WSAEFAULT;
+ }
+
+ //
+ // Copy in the context information.
+ //
+
+ RtlCopyMemory( optvalue, ct, sizeof(*ct) );
+ }
+
+ *optlength = sizeof(*ct);
+
+ return NO_ERROR;
+ }
+
+ /** The only level we support is NSPROTO_IPX **/
+
+ if (level != NSPROTO_IPX)
+ return WSAEINVAL;
+
+ /** Fill in the result based on the options name **/
+
+ switch (optname) {
+
+ /** Get the current send packet type **/
+
+ case IPX_PTYPE:
+
+ /** Make sure the length is OK **/
+
+ if (*optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Set the type **/
+
+ *(UINT *)optvalue = (UINT)ct->con_sendptype;
+ *optlength = sizeof(UINT);
+ break;
+
+ /** Get the current recv packet type filter **/
+
+ case IPX_FILTERPTYPE:
+
+ /** Make sure length is OK **/
+
+ if (*optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** If option not on - return error **/
+
+ if (!(ct->con_flags & WSHCON_FILTER))
+ return WSAEINVAL;
+
+ /** Save the new value **/
+
+ *(UINT *)optvalue = (UINT)ct->con_recvptype;
+ *optlength = sizeof(UINT);
+ break;
+
+ /** Get the max DGRAM size that can be sent **/
+
+ case IPX_MAXSIZE:
+
+ /** Make sure length is OK **/
+
+ if (*optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the value from the driver **/
+
+ rc = do_tdi_action(addrhandle, MIPX_GETPKTSIZE, (PUCHAR)ibuf, sizeof(INT)*2, TRUE, NULL);
+
+ *(INT *)optvalue = ibuf[1];
+ *optlength = sizeof(int);
+
+ /** Return the result **/
+
+ return rc;
+
+ /** Get the max adapternum that is valid **/
+
+ case IPX_MAX_ADAPTER_NUM:
+
+ /** Make sure length is OK **/
+
+ if (*optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the value from the driver **/
+
+ rc = do_tdi_action(addrhandle, MIPX_ADAPTERNUM, optvalue, sizeof(INT), TRUE, NULL);
+
+ *optlength = sizeof(int);
+
+ /** Return the result **/
+
+ return rc;
+
+ /** Get SPX statistics **/
+
+ case IPX_SPXGETCONNECTIONSTATUS:
+
+ /** Make sure data length OK **/
+
+ if (*optlength < sizeof(IPX_SPXCONNSTATUS_DATA))
+ return WSAEFAULT;
+
+ /** Make sure this is for a STREAM socket **/
+
+ if ((ct->con_socktype != SOCK_STREAM) &&
+ (ct->con_socktype != SOCK_SEQPACKET)) {
+
+ return WSAEINVAL;
+ }
+
+ /** Send it to the driver **/
+
+ rc = do_tdi_action(
+ connhandle,
+ MSPX_GETSTATS,
+ optvalue,
+ *optlength,
+ FALSE,
+ NULL);
+
+ if (rc)
+ return rc;
+
+ *optlength = sizeof(IPX_SPXCONNSTATUS_DATA);
+
+ /** Return OK **/
+
+ return NO_ERROR;
+
+ /** Get the current datastream type to send pkts with **/
+
+ case IPX_DSTYPE:
+
+ /** Make sure length is OK **/
+
+ if (*optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a STREAM socket **/
+
+ if ((ct->con_socktype != SOCK_STREAM) &&
+ (ct->con_socktype != SOCK_SEQPACKET)) {
+
+ return WSAEINVAL;
+ }
+
+ /** Save the new value **/
+
+ *(UINT *)optvalue = (UINT)ct->con_dstype;
+ *optlength = sizeof(UINT);
+ break;
+
+ /** Get net information **/
+
+ case IPX_GETNETINFO:
+
+ /** Make sure data length OK **/
+
+ if (*optlength < sizeof(IPX_NETNUM_DATA))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Send it to the driver **/
+
+ rc = do_tdi_action(
+ addrhandle,
+ MIPX_GETNETINFO,
+ optvalue,
+ *optlength,
+ TRUE,
+ NULL);
+
+ if (rc) {
+ return rc;
+ }
+
+ *optlength = sizeof(IPX_NETNUM_DATA);
+
+ /** Return OK **/
+
+ return NO_ERROR;
+
+ /** Get net information without RIPping **/
+
+ case IPX_GETNETINFO_NORIP:
+
+ /** Make sure data length OK **/
+
+ if (*optlength < sizeof(IPX_NETNUM_DATA))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Send it to the driver **/
+
+ rc = do_tdi_action(
+ addrhandle,
+ MIPX_GETNETINFO_NR,
+ optvalue,
+ *optlength,
+ TRUE,
+ NULL);
+
+ if (rc) {
+ return rc;
+ }
+
+ *optlength = sizeof(IPX_NETNUM_DATA);
+
+ /** Return OK **/
+
+ return NO_ERROR;
+
+ /** Like GETNETINFO, but force a re-rip **/
+
+ case IPX_RERIPNETNUMBER:
+
+ /** Make sure data length OK **/
+
+ if (*optlength < sizeof(IPX_NETNUM_DATA))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Send it to the driver **/
+
+ rc = do_tdi_action(
+ addrhandle,
+ MIPX_RERIPNETNUM,
+ optvalue,
+ *optlength,
+ TRUE,
+ NULL);
+
+ if (rc) {
+ return rc;
+ }
+
+ *optlength = sizeof(IPX_NETNUM_DATA);
+
+ /** Return OK **/
+
+ return NO_ERROR;
+
+ /** Get card information **/
+
+ case IPX_ADDRESS_NOTIFY:
+
+ /** We need the action header, the data, and the event handle **/
+
+ if (*optlength < (INT)(FIELD_OFFSET(NWLINK_ACTION, Data[0]) + sizeof(IPX_ADDRESS_DATA) + sizeof(HANDLE)))
+ return WSAEFAULT;
+
+ /** Otherwise just fall through **/
+
+ case IPX_ADDRESS:
+
+ /** Make sure data length OK **/
+
+ if (*optlength < sizeof(IPX_OLD_ADDRESS_DATA))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Send it to the driver **/
+
+ if (optname == IPX_ADDRESS) {
+
+ rc = do_tdi_action(
+ addrhandle,
+ MIPX_GETCARDINFO,
+ optvalue,
+ *optlength,
+ TRUE,
+ NULL);
+
+ } else {
+
+ rc = do_tdi_action(
+ addrhandle,
+ MIPX_NOTIFYCARDINFO,
+ optvalue,
+ *optlength - sizeof(HANDLE),
+ TRUE,
+ (PHANDLE)(optvalue + FIELD_OFFSET(NWLINK_ACTION, Data[0]) + sizeof(IPX_ADDRESS_DATA)));
+ }
+
+ if (rc) {
+ p = (PIPX_ADDRESS_DATA)optvalue;
+ memset(p->netnum, 0xFF, 4);
+ memset(p->nodenum, 0xFF, 6);
+ return rc;
+ }
+
+ /** Return OK **/
+
+ if (*optlength < sizeof(IPX_ADDRESS_DATA)) {
+ *optlength = sizeof(IPX_OLD_ADDRESS_DATA);
+ } else if (*optlength < sizeof(IPX_ADDRESS_DATA)) {
+ *optlength = sizeof(IPX_ADDRESS_DATA);
+ }
+
+ return NO_ERROR;
+
+ /** All others are error **/
+
+ default:
+ return WSAENOPROTOOPT;
+ }
+
+ /** All is OK **/
+
+ return NO_ERROR;
+}
+
+/*page***************************************************************
+ W S H S e t S o c k e t I n f o r m a t i o n
+
+ This routine sets information about a socket for those
+ options supported in this helper DLL. This routine
+ is called when a setsockopt call is made and the option/level
+ passed is unknown to the WinSock DLL.
+
+ Arguments - context = Context ptr from WSAOpenSocket
+ handle = Socket handle
+ addrhandle = Datagram Handle
+ connhandle = Connection Handle
+ level = Level from getsockopt call
+ optname = Option name from getsockopt call
+ optvalue = Option value ptr from getsockopt call
+ optlength = Option length field from getsockopt call
+
+ Returns - NO_ERROR = Operation succeeded OK
+ Else = WinSock error code
+*********************************************************************/
+INT WSHSetSocketInformation(PVOID context, SOCKET handle,
+ HANDLE addrhandle, HANDLE connhandle,
+ INT level, INT optname, PCHAR optvalue,
+ INT optlength)
+{
+ PWSHIPX_SOCKET_CONTEXT ct;
+ INT rc;
+
+ /** Get ptr to context **/
+
+ ct = (PWSHIPX_SOCKET_CONTEXT)context;
+
+ //
+ // Check if this is an internal request for context information.
+ //
+
+ if ( level == SOL_INTERNAL && optname == SO_CONTEXT ) {
+
+ //
+ // The Windows Sockets DLL is requesting that we set context
+ // information for a new socket. If the new socket was
+ // accept()'ed, then we have already been notified of the socket
+ // and HelperDllSocketContext will be valid. If the new socket
+ // was inherited or duped into this process, then this is our
+ // first notification of the socket and HelperDllSocketContext
+ // will be equal to NULL.
+ //
+ // Insure that the context information being passed to us is
+ // sufficiently large.
+ //
+
+ if ( optlength < sizeof(*ct) ) {
+ return WSAEINVAL;
+ }
+
+ if ( ct == NULL ) {
+
+ //
+ // This is our notification that a socket handle was
+ // inherited or duped into this process. Allocate a context
+ // structure for the new socket.
+ //
+
+ ct = RtlAllocateHeap( RtlProcessHeap( ), 0, sizeof(*ct) );
+ if ( ct == NULL ) {
+ return WSAENOBUFS;
+ }
+
+ //
+ // Copy over information into the context block.
+ //
+
+ RtlCopyMemory( ct, optvalue, sizeof(*ct) );
+
+ //
+ // Tell the Windows Sockets DLL where our context information is
+ // stored so that it can return the context pointer in future
+ // calls.
+ //
+
+ *(PWSHIPX_SOCKET_CONTEXT *)optvalue = ct;
+
+ return NO_ERROR;
+
+ } else {
+
+ PWSHIPX_SOCKET_CONTEXT parentContext;
+ INT one = 1;
+
+ //
+ // The socket was accept()'ed and it needs to have the same
+ // properties as it's parent. The OptionValue buffer
+ // contains the context information of this socket's parent.
+ //
+
+ parentContext = (PWSHIPX_SOCKET_CONTEXT)optvalue;
+
+ ASSERT( ct->con_addrfam == parentContext->con_addrfam );
+ ASSERT( ct->con_socktype == parentContext->con_socktype );
+ ASSERT( ct->con_pcol == parentContext->con_pcol );
+
+ return NO_ERROR;
+ }
+ }
+
+ /** We only support level NSPROTO_IPX **/
+
+ if (level != NSPROTO_IPX)
+ return WSAEINVAL;
+
+ /** Handle the options **/
+
+ switch (optname) {
+
+ /** Set the send packet type **/
+
+ case IPX_PTYPE:
+
+ /** Make sure length is OK **/
+
+ if (optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the value and check it **/
+
+ rc = *(INT *)optvalue;
+ if ((rc < 0) || (rc > 255))
+ return WSAEINVAL;
+
+ /** Save the new value **/
+
+ ct->con_sendptype = (UCHAR)rc;
+
+ /** Send the new value down to the driver **/
+
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_SETSENDPTYPE, &ct->con_sendptype, 1, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+
+ return rc;
+
+ /** Set the recv filter for packet type **/
+
+ case IPX_FILTERPTYPE:
+
+ /** Make sure length is OK **/
+
+ if (optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the value and check it **/
+
+ rc = *(INT *)optvalue;
+ if ((rc < 0) || (rc > 255))
+ return WSAEINVAL;
+
+ /** Save the new value **/
+
+ ct->con_recvptype = (UCHAR)rc;
+ ct->con_flags |= WSHCON_FILTER;
+
+ /** Send the new value down to the driver **/
+
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_FILTERPTYPE, &ct->con_recvptype, 1, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+
+ /** **/
+
+ return rc;
+
+ /** Stop filtering recv on pkt type **/
+
+ case IPX_STOPFILTERPTYPE:
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Turn off the flag **/
+
+ ct->con_flags &= ~WSHCON_FILTER;
+
+ /** Tell the driver **/
+
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_NOFILTERPTYPE, NULL, 0, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+ break;
+
+ /** Set piggyback wait for backtraffic flag **/
+ case IPX_IMMEDIATESPXACK:
+
+ /** Get the optvalue as an INT **/
+
+ rc = *(INT *)optvalue;
+
+ /** **/
+
+ if (rc)
+ {
+ /** Turn it ON **/
+ rc = WSAEINVAL;
+ if ((ct->con_socktype == SOCK_STREAM) ||
+ (ct->con_socktype == SOCK_SEQPACKET))
+ {
+ rc = NO_ERROR;
+
+ ct->con_flags |= WSHCON_IMM_SPXACK;
+
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MSPX_NOACKWAIT, NULL, 0, TRUE, NULL);
+ }
+ }
+ else
+ {
+ /** Turn it OFF **/
+ rc = WSAEINVAL;
+ if ((ct->con_socktype == SOCK_STREAM) ||
+ (ct->con_socktype == SOCK_SEQPACKET))
+ {
+ rc = NO_ERROR;
+
+ ct->con_flags &= ~WSHCON_IMM_SPXACK;
+
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MSPX_ACKWAIT, NULL, 0, TRUE, NULL);
+ }
+ }
+
+ /** Return the result **/
+ return rc;
+
+ /** Set to recv pcol hdrs with data **/
+
+ case IPX_RECVHDR:
+
+ /** Get the optvalue as an INT **/
+ rc = *(INT *)optvalue;
+
+ if (rc)
+ {
+ /** Turn it ON **/
+ ct->con_flags |= WSHCON_SENDHDR;
+
+ /** Send it to the driver **/
+ rc = WSAEINVAL;
+ if (ct->con_socktype == SOCK_DGRAM)
+ {
+ rc = NO_ERROR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_SENDHEADER, NULL, 0, TRUE, NULL);
+ }
+ else if ((ct->con_socktype == SOCK_STREAM) ||
+ (ct->con_socktype == SOCK_SEQPACKET))
+ {
+ /** Do this on address handle **/
+ rc = NO_ERROR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MSPX_SENDHEADER, NULL, 0, TRUE, NULL);
+ }
+ }
+ else
+ {
+
+ /** Turn it OFF **/
+ ct->con_flags &= ~WSHCON_SENDHDR;
+
+ /** Send it to the driver **/
+ rc = WSAEINVAL;
+ if (ct->con_socktype == SOCK_DGRAM)
+ {
+ rc = NO_ERROR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_NOSENDHEADER, NULL, 0, TRUE, NULL);
+ }
+ else if ((ct->con_socktype == SOCK_STREAM) ||
+ (ct->con_socktype == SOCK_SEQPACKET))
+ {
+ rc = NO_ERROR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MSPX_NOSENDHEADER, NULL, 0, TRUE, NULL);
+ }
+ }
+
+ /** Return the result **/
+ return rc;
+
+ /** Set the Datastream type to send pkts with **/
+
+ case IPX_DSTYPE:
+
+ /** Make sure length is OK **/
+
+ if (optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a STREAM socket **/
+
+ if ((ct->con_socktype != SOCK_STREAM) &&
+ (ct->con_socktype != SOCK_SEQPACKET)) {
+
+ return WSAEINVAL;
+ }
+
+ /** Get the value and check it **/
+
+ rc = *(INT *)optvalue;
+ if ((rc < 0) || (rc > 255))
+ return WSAEINVAL;
+
+ /** Save the new value **/
+
+ ct->con_dstype = (UCHAR)rc;
+
+ /** Send the new value down to the driver **/
+
+ if (connhandle)
+ rc = do_tdi_action(connhandle, MSPX_SETDATASTREAM, &ct->con_dstype, 1, FALSE, NULL);
+ else
+ rc = 0;
+
+ /** **/
+
+ return rc;
+
+ /** Set the extended address option **/
+
+ case IPX_EXTENDED_ADDRESS:
+
+ /** Make sure length is OK **/
+
+ if (optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the optvalue as an INT **/
+
+ rc = *(INT *)optvalue;
+
+ /** **/
+
+ if (rc) {
+
+ /** Send the option down to the driver **/
+
+ ct->con_flags |= WSHCON_EXTADDR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_SENDADDROPT, NULL, 0, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+ }
+ else {
+
+ /** Send the option down to the driver **/
+
+ ct->con_flags &= ~WSHCON_EXTADDR;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_NOSENDADDROPT, NULL, 0, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+ }
+ return rc;
+
+
+ /** Set the broadcast reception **/
+
+ case IPX_RECEIVE_BROADCAST:
+
+ /** Make sure length is OK **/
+
+ if (optlength < sizeof(INT))
+ return WSAEFAULT;
+
+ /** Make sure this is for a DGRAM socket **/
+
+ if (ct->con_socktype != SOCK_DGRAM)
+ return WSAEINVAL;
+
+ /** Get the optvalue as an INT **/
+
+ rc = *(INT *)optvalue;
+
+ /** **/
+
+ if (rc) {
+
+ /** Send the option down to the driver **/
+
+ ct->con_flags |= WSHCON_RCVBCAST;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_RCVBCAST, NULL, 0, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+ }
+ else {
+
+ /** Send the option down to the driver **/
+
+ ct->con_flags &= ~WSHCON_RCVBCAST;
+ if (addrhandle)
+ rc = do_tdi_action(addrhandle, MIPX_NORCVBCAST, NULL, 0, TRUE, NULL);
+ else
+ rc = NO_ERROR;
+ }
+ return rc;
+
+ /** All others return error **/
+
+ default:
+ return WSAENOPROTOOPT;
+ }
+
+ /** All Done OK **/
+
+ return NO_ERROR;
+}
+
+/*page***************************************************************
+ W S H G e t W i l d c a r d S o c k a d d r
+
+ This routing returns a wilcard socket address for the
+ sockets DLL to use.
+
+ Arguments - context = Context ptr from WSAOpenSocket
+ addrp = Ptr to where to store the address
+ addrlen = Ptr to where to store length of address
+
+ Returns - NO_ERROR = Operation succeeded OK
+ Else = WinSock error code
+*********************************************************************/
+INT WSHGetWildcardSockaddr(PVOID context, PSOCKADDR addrp, PINT addrlen)
+{
+
+ /**
+ Setup the address as the address family +
+ all 0's for the rest.
+ **/
+
+ memset(addrp, 0, sizeof(SOCKADDR));
+ addrp->sa_family = AF_NS;
+
+ /** Set the address length **/
+
+ *addrlen = sizeof(SOCKADDR);
+
+ /** Return OK **/
+
+ return NO_ERROR;
+}
+
+/*page***************************************************************
+ i s _ t r i p l e _ i n _ l i s t
+
+ Check to see if the given triple is in the given
+ triple list.
+
+ Arguments - tlist = Ptr to the triple list
+ tlen = Num entries in the triple list
+ addrfam = Address family to look for
+ socktype = Socket Type to look for
+ pcol = Protocol to look for
+
+ Returns - TRUE = Yes
+ FALSE = No
+*********************************************************************/
+BOOLEAN is_triple_in_list(PMAPPING_TRIPLE tlist, ULONG tlen,
+ INT addrfam, INT socktype, INT pcol)
+{
+ ULONG i;
+
+ /**
+ Go thru the list and search to see if we can
+ find the given triple in the list.
+ **/
+
+ for (i = 0 ; i < tlen ; i++,tlist++) {
+
+ /** If it matches - return OK **/
+
+ if ((addrfam == tlist->triple_addrfam) &&
+ (socktype == tlist->triple_socktype) &&
+ (pcol == tlist->triple_protocol))
+
+ return TRUE;
+ }
+
+ /** Not Found **/
+
+ return FALSE;
+}
+
+/*page***************************************************************
+ W S H E n u m P r o t o c o l s
+
+ Enumerates IPX/SPX protocols.
+
+ Returns - NO_ERROR or an error code.
+*********************************************************************/
+INT
+WSHEnumProtocols (
+ IN LPINT lpiProtocols,
+ IN LPTSTR lpTransportKeyName,
+ IN OUT LPVOID lpProtocolBuffer,
+ IN OUT LPDWORD lpdwBufferLength
+ )
+{
+ DWORD bytesRequired;
+ PPROTOCOL_INFOW protocolInfo;
+ BOOL useSpx = FALSE;
+ BOOL useSpx2 = FALSE;
+ BOOL useIpx = FALSE;
+ BOOL spxString;
+ DWORD i;
+ PWCHAR namePtr;
+ INT entriesReturned = 0;
+
+ //
+ // Determine whether we should return information for IPX or SPX.
+ //
+
+ if ( _wcsicmp( L"NwlnkIpx", (LPWSTR)lpTransportKeyName ) == 0 ) {
+ spxString = FALSE;
+ } else {
+ spxString = TRUE;
+ }
+
+ //
+ // Make sure that the caller cares about SPX, SPX2, and/or IPX.
+ //
+
+ if ( ARGUMENT_PRESENT( lpiProtocols ) ) {
+
+ for ( i = 0; lpiProtocols[i] != 0; i++ ) {
+ if ( lpiProtocols[i] == NSPROTO_SPX && spxString ) {
+ useSpx = TRUE;
+ }
+ if ( lpiProtocols[i] == NSPROTO_SPXII && spxString ) {
+ useSpx2 = TRUE;
+ }
+ if ( lpiProtocols[i] == NSPROTO_IPX && !spxString ) {
+ useIpx = TRUE;
+ }
+ }
+
+ } else {
+
+ useSpx = FALSE;
+ useSpx2 = spxString;
+ useIpx = !spxString;
+ }
+
+ if ( !useSpx && !useSpx2 && !useIpx ) {
+ *lpdwBufferLength = 0;
+ return 0;
+ }
+
+ //
+ // Make sure that the caller has specified a sufficiently large
+ // buffer.
+ //
+
+ bytesRequired = (sizeof(PROTOCOL_INFO) * 3) +
+ ( (wcslen( SPX_NAME ) + 1) * sizeof(WCHAR)) +
+ ( (wcslen( SPX2_NAME ) + 1) * sizeof(WCHAR)) +
+ ( (wcslen( IPX_NAME ) + 1) * sizeof(WCHAR));
+
+ if ( bytesRequired > *lpdwBufferLength ) {
+ *lpdwBufferLength = bytesRequired;
+ return -1;
+ }
+
+ //
+ // Initialize local variables.
+ //
+
+ protocolInfo = lpProtocolBuffer;
+ namePtr = (PWCHAR)( (PCHAR)lpProtocolBuffer + *lpdwBufferLength );
+
+ //
+ // Fill in SPX info, if requested.
+ //
+
+ if ( useSpx ) {
+
+ entriesReturned += 1;
+
+ protocolInfo->dwServiceFlags = XP_GUARANTEED_DELIVERY |
+ XP_MESSAGE_ORIENTED |
+ XP_PSEUDO_STREAM |
+ XP_GUARANTEED_ORDER |
+ XP_FRAGMENTATION;
+ protocolInfo->iAddressFamily = AF_IPX;
+ protocolInfo->iMaxSockAddr = 0x10;
+ protocolInfo->iMinSockAddr = 0xE;
+ protocolInfo->iSocketType = SOCK_SEQPACKET;
+ protocolInfo->iProtocol = NSPROTO_SPX;
+ protocolInfo->dwMessageSize = 0xFFFFFFFF;
+
+ namePtr = namePtr - (wcslen( SPX_NAME) + 1);
+ protocolInfo->lpProtocol = namePtr;
+ wcscpy( protocolInfo->lpProtocol, SPX_NAME );
+
+ protocolInfo += 1;
+ }
+
+ //
+ // Fill in SPX II info, if requested.
+ //
+
+ if ( useSpx2 ) {
+
+ entriesReturned += 1;
+
+ protocolInfo->dwServiceFlags = XP_GUARANTEED_DELIVERY |
+ XP_MESSAGE_ORIENTED |
+ XP_PSEUDO_STREAM |
+ XP_GRACEFUL_CLOSE |
+ XP_GUARANTEED_ORDER |
+ XP_FRAGMENTATION;
+ protocolInfo->iAddressFamily = AF_IPX;
+ protocolInfo->iMaxSockAddr = 0x10;
+ protocolInfo->iMinSockAddr = 0xE;
+ protocolInfo->iSocketType = SOCK_SEQPACKET;
+ protocolInfo->iProtocol = NSPROTO_SPXII;
+ protocolInfo->dwMessageSize = 0xFFFFFFFF;
+
+ namePtr = namePtr - (wcslen( SPX2_NAME) + 1);
+ protocolInfo->lpProtocol = namePtr;
+ wcscpy( protocolInfo->lpProtocol, SPX2_NAME );
+
+ protocolInfo += 1;
+ }
+
+ //
+ // Fill in IPX info, if requested.
+ //
+
+ if ( useIpx ) {
+
+ entriesReturned += 1;
+
+ protocolInfo->dwServiceFlags = XP_CONNECTIONLESS |
+ XP_MESSAGE_ORIENTED |
+ XP_SUPPORTS_BROADCAST |
+ XP_SUPPORTS_MULTICAST |
+ XP_FRAGMENTATION;
+ protocolInfo->iAddressFamily = AF_IPX;
+ protocolInfo->iMaxSockAddr = 0x10;
+ protocolInfo->iMinSockAddr = 0xE;
+ protocolInfo->iSocketType = SOCK_DGRAM;
+ protocolInfo->iProtocol = NSPROTO_IPX;
+ protocolInfo->dwMessageSize = 576;
+
+ namePtr = namePtr - (wcslen( IPX_NAME) + 1);
+ protocolInfo->lpProtocol = namePtr;
+ wcscpy( protocolInfo->lpProtocol, IPX_NAME );
+ }
+
+ *lpdwBufferLength = bytesRequired;
+
+ return entriesReturned;
+
+} // WSHEnumProtocols
+
+
+#define _IPX_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_TRANSPORT, request, method, FILE_ANY_ACCESS)
+#define IOCTL_IPX_LOAD_SPX _IPX_CONTROL_CODE( 0x5678, METHOD_BUFFERED )
+
+DWORD
+WshLoadSpx(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Starts the nwlnkspx.sys driver by submitting a special ioctl
+ to ipx, which calls ZwLoadDriver() for us.
+
+Arguments:
+
+ none
+
+Returns:
+
+ Error return from the load operation.
+
+++*/
+{
+ DWORD err = NO_ERROR;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING FileString;
+ WCHAR FileName[] = L"\\Device\\NwlnkIpx";
+ NTSTATUS Status;
+
+ RtlInitUnicodeString (&FileString, FileName);
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &FileString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(
+ &FileHandle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ if (!NT_SUCCESS(Status)) {
+
+ err = ERROR_FILE_NOT_FOUND;
+
+ } else {
+
+ Status = NtDeviceIoControlFile(
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_IPX_LOAD_SPX,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ if (Status == STATUS_IMAGE_ALREADY_LOADED) {
+
+ err = ERROR_SERVICE_ALREADY_RUNNING;
+
+ //
+ // #36451
+ // If the service controller loads SPX ("net start nwlnkspx", or due to dependency of RPC on SPX)
+ // then we get this error the first time too. Keep a note of that.
+ //
+ // BUGBUG: we still leak a handle per process since the handle to the driver is actually created
+ // in the system process' context. The ideal way to fix this should be to have IPX associate the
+ // handle with the current process (so handle is destroyed when the process dies) or to have the
+ // dll tell IPX to close the handle it opened earlier.
+ //
+ SpxLoaded = TRUE;
+
+ } else if (!NT_SUCCESS(Status)) {
+
+ err = ERROR_IO_DEVICE;
+
+ } else {
+ SpxLoaded = TRUE;
+ }
+
+ NtClose (FileHandle);
+
+ }
+
+ return(err);
+}
+
+/*page***************************************************************
+ W S H G e t P r o v i d e r G u i d
+
+ Queries the GUID identifier for this protocol.
+
+ Returns - NO_ERROR or an error code.
+*********************************************************************/
+INT
+WINAPI
+WSHGetProviderGuid (
+ IN LPWSTR ProviderName,
+ OUT LPGUID ProviderGuid
+ )
+{
+
+ if( ProviderName == NULL ||
+ ProviderGuid == NULL ) {
+
+ return WSAEFAULT;
+
+ }
+
+ if( _wcsicmp( ProviderName, L"NwlnkIpx" ) == 0 ) {
+
+ RtlCopyMemory(
+ ProviderGuid,
+ &IpxProviderGuid,
+ sizeof(GUID)
+ );
+
+ return NO_ERROR;
+
+ }
+
+ if( _wcsicmp( ProviderName, L"NwlnkSpx" ) == 0 ) {
+
+ RtlCopyMemory(
+ ProviderGuid,
+ &SpxProviderGuid,
+ sizeof(GUID)
+ );
+
+ return NO_ERROR;
+
+ }
+
+ return WSAEINVAL;
+
+} // WSHGetProviderGuid
+
diff --git a/private/ntos/tdi/isn/sockhelp/wshisn.c b/private/ntos/tdi/isn/sockhelp/wshisn.c
new file mode 100644
index 000000000..75cb70f40
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/wshisn.c
@@ -0,0 +1,323 @@
+/****************************************************************************
+* (c) Copyright 1993 Micro Computer Systems, Inc. All rights reserved.
+*****************************************************************************
+*
+* Title: IPX/SPX WinSock Helper DLL for Windows NT
+*
+* Module: ipx/sockhelp/wshnwlnk.c
+*
+* Version: 1.00.00
+*
+* Date: 04-08-93
+*
+* Author: Brian Walker
+*
+*****************************************************************************
+*
+* Change Log:
+*
+* Date DevSFC Comment
+* -------- ------ -------------------------------------------------------
+*
+*****************************************************************************
+*
+* Functional Description:
+*
+****************************************************************************/
+#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 <wsipx.h>
+#include <wsnwlink.h>
+
+/*page****************************************************************
+ These are the triples we support.
+*********************************************************************/
+typedef struct _MAPPING_TRIPLE {
+ INT triple_addrfam;
+ INT triple_socktype;
+ INT triple_protocol;
+} MAPPING_TRIPLE, *PMAPPING_TRIPLE;
+
+MAPPING_TRIPLE stream_triples[] = {
+ { AF_NS, SOCK_STREAM, NSPROTO_SPX },
+ { AF_NS, SOCK_SEQPACKET, NSPROTO_SPX },
+ { AF_NS, SOCK_STREAM, NSPROTO_SPXII },
+ { AF_NS, SOCK_SEQPACKET, NSPROTO_SPXII },
+};
+int stream_num_triples = 4; /* When SPXII - set to 4 */
+int stream_table_size = sizeof(stream_triples);
+
+/**
+ For IPX we assign the default packet type according to the
+ protocol type used. The user can also we setsockopt
+ to set the packet type.
+**/
+
+MAPPING_TRIPLE dgram_triples[] = {
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+1 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+2 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+3 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+4 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+5 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+6 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+7 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+8 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+9 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+10 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+11 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+12 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+13 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+14 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+15 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+16 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+17 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+18 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+19 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+20 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+21 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+22 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+23 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+24 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+25 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+26 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+27 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+28 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+29 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+30 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+31 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+32 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+33 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+34 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+35 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+36 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+37 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+38 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+39 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+40 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+41 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+42 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+43 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+44 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+45 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+46 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+47 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+48 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+49 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+50 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+51 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+52 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+53 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+54 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+55 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+56 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+57 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+58 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+59 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+60 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+61 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+62 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+63 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+64 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+65 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+66 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+67 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+68 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+69 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+70 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+71 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+72 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+73 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+74 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+75 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+76 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+77 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+78 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+79 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+80 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+81 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+82 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+83 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+84 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+85 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+86 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+87 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+88 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+89 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+90 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+91 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+92 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+93 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+94 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+95 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+96 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+97 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+98 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+99 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+100 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+101 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+102 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+103 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+104 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+105 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+106 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+107 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+108 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+109 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+110 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+111 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+112 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+113 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+114 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+115 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+116 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+117 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+118 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+119 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+120 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+121 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+122 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+123 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+124 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+125 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+126 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+127 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+128 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+129 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+130 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+131 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+132 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+133 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+134 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+135 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+136 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+137 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+138 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+139 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+140 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+141 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+142 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+143 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+144 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+145 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+146 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+147 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+148 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+149 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+150 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+151 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+152 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+153 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+154 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+155 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+156 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+157 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+158 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+159 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+160 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+161 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+162 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+163 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+164 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+165 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+166 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+167 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+168 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+169 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+170 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+171 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+172 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+173 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+174 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+175 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+176 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+177 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+178 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+179 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+180 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+181 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+182 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+183 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+184 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+185 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+186 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+187 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+188 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+189 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+190 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+191 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+192 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+193 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+194 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+195 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+196 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+197 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+198 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+199 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+200 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+201 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+202 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+203 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+204 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+205 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+206 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+207 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+208 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+209 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+210 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+211 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+212 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+213 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+214 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+215 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+216 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+217 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+218 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+219 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+220 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+221 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+222 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+223 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+224 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+225 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+226 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+227 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+228 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+229 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+230 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+231 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+232 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+233 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+234 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+235 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+236 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+237 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+238 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+239 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+240 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+241 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+242 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+243 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+244 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+245 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+246 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+247 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+248 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+249 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+250 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+251 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+252 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+253 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+254 },
+ { AF_NS, SOCK_DGRAM, NSPROTO_IPX+255 }
+};
+int dgram_num_triples = 256;
+int dgram_table_size = sizeof(dgram_triples);
diff --git a/private/ntos/tdi/isn/sockhelp/wshisn.def b/private/ntos/tdi/isn/sockhelp/wshisn.def
new file mode 100644
index 000000000..c9eecc2a4
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/wshisn.def
@@ -0,0 +1,21 @@
+LIBRARY WSHISN
+
+DESCRIPTION 'ISN Windows NT Sockets Helper DLL'
+
+CODE PRELOAD FIXED
+DATA PRELOAD FIXED SINGLE
+
+HEAPSIZE 1024
+STACKSIZE 16384
+
+EXPORTS
+ WSHGetSockaddrType
+ WSHGetSocketInformation
+ WSHGetWinsockMapping
+ WSHNotify
+ WSHOpenSocket
+ WSHSetSocketInformation
+ WSHGetWildcardSockaddr
+ WSHEnumProtocols
+ WSHGetProviderGuid
+
diff --git a/private/ntos/tdi/isn/sockhelp/wshisn.rc b/private/ntos/tdi/isn/sockhelp/wshisn.rc
new file mode 100644
index 000000000..e58fcaaf7
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/wshisn.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "NWLINK2 Socket Helper DLL"
+#define VER_INTERNALNAME_STR "wshisn.DLL"
+
+#include "common.ver"
+
diff --git a/private/ntos/tdi/isn/sockhelp/wshutil.c b/private/ntos/tdi/isn/sockhelp/wshutil.c
new file mode 100644
index 000000000..4559bd6d0
--- /dev/null
+++ b/private/ntos/tdi/isn/sockhelp/wshutil.c
@@ -0,0 +1,189 @@
+/****************************************************************************
+* (c) Copyright 1993 Micro Computer Systems, Inc. All rights reserved.
+*****************************************************************************
+*
+* Title: IPX/SPX WinSock Helper DLL for Windows NT
+*
+* Module: ipx/sockhelp/wshutil.c
+*
+* Version: 1.00.00
+*
+* Date: 04-08-93
+*
+* Author: Brian Walker
+*
+*****************************************************************************
+*
+* Change Log:
+*
+* Date DevSFC Comment
+* -------- ------ -------------------------------------------------------
+*
+*****************************************************************************
+*
+* Functional Description:
+*
+****************************************************************************/
+#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 <isnkrnl.h>
+
+/*page*******************************************************
+ d o _ t d i _ a c t i o n
+
+ Generate a TDI_ACTION down to the streams
+ driver.
+
+ Arguments - fd = Handle to send on
+ cmd = Command to send down
+ optbuf = Ptr to options buffer
+ optlen = Ptr to options length
+ addrflag = TRUE = This is for DG/STREAM socket on addr handle
+ FALSE = This is for conn handle
+
+ Returns - A WinSock error code (NO_ERROR = OK)
+************************************************************/
+INT do_tdi_action(HANDLE fd, ULONG cmd, PUCHAR optbuf, INT optlen, BOOLEAN addrflag, PHANDLE eventhandle OPTIONAL)
+{
+ NTSTATUS status;
+ PSTREAMS_TDI_ACTION tdibuf;
+ ULONG tdilen;
+ IO_STATUS_BLOCK iostat;
+ HANDLE event;
+
+
+ /** If the eventhandle is passed, it also means that the **/
+ /** NWLINK_ACTION header is pre-allocated in the buffer, **/
+ /** although we still have to fill the header in here. **/
+
+ if (eventhandle == NULL) {
+
+ /** Get the length of the buffer we need to allocate **/
+
+ tdilen = FIELD_OFFSET(STREAMS_TDI_ACTION,Buffer) + sizeof(ULONG) + optlen;
+
+ /** Allocate a buffer to use for the action **/
+
+ tdibuf = RtlAllocateHeap(RtlProcessHeap(), 0, tdilen);
+ if (tdibuf == NULL) {
+ return WSAENOBUFS;
+ }
+
+ } else {
+
+ tdilen = optlen;
+ tdibuf = (PSTREAMS_TDI_ACTION)optbuf;
+
+ }
+
+ /** Set the datagram option **/
+
+ RtlMoveMemory(&tdibuf->Header.TransportId, "MISN", 4);
+ tdibuf->DatagramOption = addrflag;
+
+ /**
+ Fill out the buffer, the buffer looks like this:
+
+ ULONG cmd
+ data passed.
+ **/
+
+ memcpy(tdibuf->Buffer, &cmd, sizeof(ULONG));
+
+ if (eventhandle == NULL) {
+
+ tdibuf->BufferLength = sizeof(ULONG) + optlen;
+
+ RtlMoveMemory(tdibuf->Buffer + sizeof(ULONG), optbuf, optlen);
+
+ /** Create an event to wait on **/
+
+ status = NtCreateEvent(
+ &event,
+ EVENT_ALL_ACCESS,
+ NULL,
+ SynchronizationEvent,
+ FALSE);
+
+ /** If no event - then return error **/
+
+ if (!NT_SUCCESS(status)) {
+ RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
+ return WSAENOBUFS;
+ }
+
+ } else {
+
+ tdibuf->BufferLength = sizeof(ULONG) + optlen - FIELD_OFFSET (NWLINK_ACTION, Data[0]);
+
+ /** Use the event handle passed in **/
+
+ event = *eventhandle;
+
+ }
+
+ /** **/
+
+ status = NtDeviceIoControlFile(
+ fd,
+ event,
+ NULL,
+ NULL,
+ &iostat,
+ IOCTL_TDI_ACTION,
+ NULL,
+ 0,
+ tdibuf,
+ tdilen);
+
+
+ if (eventhandle == NULL) {
+
+ /** If pending - wait for it to finish **/
+
+ if (status == STATUS_PENDING) {
+ status = NtWaitForSingleObject(event, FALSE, NULL);
+ ASSERT(status == 0);
+ status = iostat.Status;
+ }
+
+ /** Close the event **/
+
+ NtClose(event);
+
+ }
+
+ /** If we get an error - return it **/
+
+ if (!NT_SUCCESS(status)) {
+ if (eventhandle == NULL) {
+ RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
+ }
+ return WSAEINVAL;
+ }
+
+ if (eventhandle == NULL) {
+
+ /** Copy the returned back to optbuf if needed */
+
+ if (optlen) {
+ RtlMoveMemory (optbuf, tdibuf->Buffer + sizeof(ULONG), optlen);
+ }
+
+ RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
+
+ }
+
+ /** Return OK **/
+
+ return NO_ERROR;
+}