Implemented EnumProtocolA/W.

diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 38b423e..1e1aab8 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -472,7 +472,7 @@
 winsock/libws2_32.@LIBEXT@: libuser32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 winspool/libwinspool.drv.@LIBEXT@: libadvapi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 wow32/libwow32.@LIBEXT@: libkernel32.@LIBEXT@
-wsock32/libwsock32.@LIBEXT@: libws2_32.@LIBEXT@ libntdll.@LIBEXT@
+wsock32/libwsock32.@LIBEXT@: libws2_32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 x11drv/libx11drv.@LIBEXT@: libuser32.@LIBEXT@ libgdi32.@LIBEXT@ libkernel32.@LIBEXT@
 
 $(DLLFILES): dummy
diff --git a/dlls/wsock32/Makefile.in b/dlls/wsock32/Makefile.in
index a925ff3..4c3801b 100644
--- a/dlls/wsock32/Makefile.in
+++ b/dlls/wsock32/Makefile.in
@@ -7,7 +7,9 @@
 LDDLLFLAGS = @LDDLLFLAGS@
 SYMBOLFILE = $(MODULE).tmp.o
 
-C_SRCS = socket.c
+C_SRCS = \
+	protocol.c \
+	socket.c
 
 @MAKE_DLL_RULES@
 
diff --git a/dlls/wsock32/protocol.c b/dlls/wsock32/protocol.c
new file mode 100644
index 0000000..92f2aae
--- /dev/null
+++ b/dlls/wsock32/protocol.c
@@ -0,0 +1,250 @@
+/*
+ * WSOCK32 specific functions
+ *
+ * Copyright (C) 2001 Stefan Leichter
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include "winbase.h"
+#include "debugtools.h"
+#include "heap.h"
+#include "nspapi.h"
+#include "winsock.h"
+#include "wsipx.h"
+#include "wshisotp.h"
+
+DEFAULT_DEBUG_CHANNEL(winsock);
+
+/* name of the protocols
+ */
+static WCHAR NameIpx[]   = {'I', 'P', 'X', '\0'};
+static WCHAR NameSpx[]   = {'S', 'P', 'X', '\0'};
+static WCHAR NameSpxII[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'};
+static WCHAR NameTcp[]   = {'T', 'C', 'P', '/', 'I', 'P', '\0'};
+static WCHAR NameUdp[]   = {'U', 'D', 'P', '/', 'I', 'P', '\0'};
+
+/*****************************************************************************
+ *          WSOCK32_EnterSingleProtocol [internal]
+ *
+ *    enters the protocol informations of one given protocol into the
+ *    given buffer. If the given buffer is too small only the required size for
+ *    the protocols are returned.
+ *
+ * RETURNS
+ *    The number of protocols entered into the buffer
+ *
+ * BUGS
+ *    - only implemented for IPX, SPX, SPXII, TCP, UDP
+ *    - there is no check that the operating system supports the returned
+ *      protocols
+ */
+static INT WSOCK32_EnterSingleProtocol( INT iProtocol,
+                                        PROTOCOL_INFOA* lpBuffer,
+                                        LPDWORD lpSize, BOOL unicode)
+{ DWORD  dwLength = 0, dwOldSize = *lpSize;
+  INT    iAnz = 1;
+  WCHAR  *lpProtName = NULL;
+
+  *lpSize = sizeof( PROTOCOL_INFOA);
+  switch (iProtocol) {
+    case IPPROTO_TCP :
+        dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameTcp)+1) :
+                               WideCharToMultiByte( CP_ACP, 0, NameTcp, -1,
+                                                    NULL, 0, NULL, NULL);
+      break;
+    case IPPROTO_UDP :
+        dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameUdp)+1) :
+                               WideCharToMultiByte( CP_ACP, 0, NameUdp, -1,
+                                                    NULL, 0, NULL, NULL);
+      break;
+    case NSPROTO_IPX :
+        dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameIpx)+1) :
+                               WideCharToMultiByte( CP_ACP, 0, NameIpx, -1,
+                                                    NULL, 0, NULL, NULL);
+      break;
+    case NSPROTO_SPX :
+        dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameSpx)+1) :
+                               WideCharToMultiByte( CP_ACP, 0, NameSpx, -1,
+                                                    NULL, 0, NULL, NULL);
+      break;
+    case NSPROTO_SPXII :
+        dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameSpxII)+1) :
+                               WideCharToMultiByte( CP_ACP, 0, NameSpxII, -1,
+                                                    NULL, 0, NULL, NULL);
+      break;
+    default:
+        *lpSize = 0;
+        if ((iProtocol == ISOPROTO_TP4) || (iProtocol == NSPROTO_SPX))
+          FIXME("Protocol <%s> not implemented\n",
+                (iProtocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
+        else
+          FIXME("unknown Protocol <0x%08x>\n", iProtocol);
+      break;
+  }
+  *lpSize += dwLength;
+
+  if ( !lpBuffer || !*lpSize || (*lpSize > dwOldSize))
+     return 0;
+
+  memset( lpBuffer, 0, dwOldSize);
+
+  lpBuffer->lpProtocol = (LPSTR) &lpBuffer[ iAnz];
+  lpBuffer->iProtocol  = iProtocol;
+
+  switch (iProtocol) {
+    case IPPROTO_TCP :
+        lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_EXPEDITED_DATA     |
+                                   XP_GRACEFUL_CLOSE     | XP_GUARANTEED_ORDER   |
+                                   XP_GUARANTEED_DELIVERY;
+        lpBuffer->iAddressFamily = WS_AF_INET;
+        lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iMinSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iSocketType    = SOCK_STREAM;
+        lpBuffer->dwMessageSize  = 0;
+        lpProtName = NameTcp;
+      break;
+    case IPPROTO_UDP :
+        lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_SUPPORTS_BROADCAST |
+                                   XP_SUPPORTS_MULTICAST | XP_MESSAGE_ORIENTED   |
+                                   XP_CONNECTIONLESS;
+        lpBuffer->iAddressFamily = WS_AF_INET;
+        lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iMinSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iSocketType    = SOCK_DGRAM;
+        lpBuffer->dwMessageSize  = 65457; /* NT4 SP5 */
+        lpProtName = NameUdp;
+      break;
+    case NSPROTO_IPX :
+        lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_SUPPORTS_BROADCAST |
+                                   XP_SUPPORTS_MULTICAST | XP_MESSAGE_ORIENTED   |
+                                   XP_CONNECTIONLESS;
+        lpBuffer->iAddressFamily = WS_AF_IPX;
+        lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
+        lpBuffer->iSocketType    = SOCK_DGRAM;
+        lpBuffer->dwMessageSize  = 576;   /* NT4 SP5 */
+        lpProtName = NameIpx;
+      break;
+    case NSPROTO_SPX :
+        lpBuffer->dwServiceFlags = XP_FRAGMENTATION      |
+                                   XP_PSEUDO_STREAM      | XP_MESSAGE_ORIENTED   |
+                                   XP_GUARANTEED_ORDER   | XP_GUARANTEED_DELIVERY;
+        lpBuffer->iAddressFamily = WS_AF_IPX;
+        lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
+        lpBuffer->iSocketType    = 5;
+        lpBuffer->dwMessageSize  = -1;    /* NT4 SP5 */
+        lpProtName = NameSpx;
+      break;
+    case NSPROTO_SPXII :
+        lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_GRACEFUL_CLOSE     |
+                                   XP_PSEUDO_STREAM      | XP_MESSAGE_ORIENTED   |
+                                   XP_GUARANTEED_ORDER   | XP_GUARANTEED_DELIVERY;
+        lpBuffer->iAddressFamily = WS_AF_IPX;
+        lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
+        lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
+        lpBuffer->iSocketType    = 5;
+        lpBuffer->dwMessageSize  = -1;    /* NT4 SP5 */
+        lpProtName = NameSpxII;
+      break;
+  }
+  if (unicode)
+    strcpyW( (LPWSTR)lpBuffer->lpProtocol, lpProtName);
+  else
+    WideCharToMultiByte( CP_ACP, 0, lpProtName, -1, lpBuffer->lpProtocol,
+                         dwOldSize - iAnz * sizeof( PROTOCOL_INFOA), NULL, NULL);
+
+  return iAnz;
+}
+
+/*****************************************************************************
+ *          WSOCK32_EnumProtocol [internal]
+ *
+ *    Enters the information about installed protocols into a given buffer
+ *
+ * RETURNS
+ *    SOCKET_ERROR if the buffer is to small for the requested protocol infos
+ *    on success the number of protocols inside the buffer
+ *
+ * NOTE
+ *    NT4SP5 does not return SPX if lpiProtocols == NULL
+ *
+ * BUGS
+ *    - NT4SP5 returns in addition these list of NETBIOS protocols
+ *      (address family 17), each entry two times one for socket type 2 and 5
+ *
+ *      iProtocol   lpProtocol
+ *      0x80000000  \Device\NwlnkNb
+ *      0xfffffffa  \Device\NetBT_CBENT7
+ *      0xfffffffb  \Device\Nbf_CBENT7
+ *      0xfffffffc  \Device\NetBT_NdisWan5
+ *      0xfffffffd  \Device\NetBT_El9202
+ *      0xfffffffe  \Device\Nbf_El9202
+ *      0xffffffff  \Device\Nbf_NdisWan4
+ *
+ *    - there is no check that the operating system supports the returned
+ *      protocols
+ */
+static INT WSOCK32_EnumProtocol( LPINT lpiProtocols, PROTOCOL_INFOA* lpBuffer,
+                                 LPDWORD lpdwLength, BOOL unicode)
+{ DWORD dwCurSize, dwOldSize = *lpdwLength, dwTemp;
+  INT   anz = 0, i;
+  INT   iLocal[] = { IPPROTO_TCP, IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPXII, 0};
+
+  if (!lpiProtocols) lpiProtocols = iLocal;
+
+  *lpdwLength = 0;
+  while ( *lpiProtocols )
+  { dwCurSize = 0;
+    WSOCK32_EnterSingleProtocol( *lpiProtocols, NULL, &dwCurSize, unicode);
+
+    if ( lpBuffer && dwCurSize && ((*lpdwLength + dwCurSize) <= dwOldSize))
+    { /* reserve the required space for the current protocol_info after the
+       * last protocol_info before the start of the string buffer and adjust
+       * the references into the string buffer
+       */
+      memmove( &((char*)&lpBuffer[ anz])[dwCurSize],
+		  &lpBuffer[ anz],
+               *lpdwLength - anz * sizeof( PROTOCOL_INFOA));
+      for (i=0; i < anz; i++)
+        lpBuffer[i].lpProtocol += dwCurSize;
+
+      dwTemp = dwCurSize;
+      anz += WSOCK32_EnterSingleProtocol( *lpiProtocols, &lpBuffer[anz],
+                                          &dwTemp, unicode);
+    }
+
+    *lpdwLength += dwCurSize;
+    lpiProtocols++;
+  }
+
+  if (dwOldSize < *lpdwLength) anz = SOCKET_ERROR;
+
+  return anz;
+}
+
+/*****************************************************************************
+ *          EnumProtocolsA       [WSOCK32.1111]
+ *
+ *    see function WSOCK32_EnumProtocol for RETURNS, BUGS
+ */
+INT WINAPI EnumProtocolsA( LPINT lpiProtocols, LPVOID lpBuffer,
+                           LPDWORD lpdwLength)
+{
+   return WSOCK32_EnumProtocol( lpiProtocols, (PROTOCOL_INFOA*) lpBuffer,
+                                lpdwLength, FALSE);
+}
+
+/*****************************************************************************
+ *          EnumProtocolsW       [WSOCK32.1112]
+ *
+ *    see function WSOCK32_EnumProtocol for RETURNS, BUGS
+ */
+INT WINAPI EnumProtocolsW( LPINT lpiProtocols, LPVOID lpBuffer,
+                           LPDWORD lpdwLength)
+{
+   return WSOCK32_EnumProtocol( lpiProtocols, (PROTOCOL_INFOA*) lpBuffer,
+                                lpdwLength, TRUE);
+}
diff --git a/dlls/wsock32/wsock32.spec b/dlls/wsock32/wsock32.spec
index ed3dc93..d5182b0 100644
--- a/dlls/wsock32/wsock32.spec
+++ b/dlls/wsock32/wsock32.spec
@@ -2,6 +2,7 @@
 type	win32
 
 import	ws2_32.dll
+import	kernel32.dll
 import	ntdll.dll
 
 debug_channels (winsock)
@@ -70,8 +71,8 @@
 1108 stdcall s_perror(str) WS_s_perror
 1109 stub GetAddressByNameA
 1110 stub GetAddressByNameW
-#1111 stub EnumProtocolsA
-#1112 stub EnumProtocolsW
+1111 stdcall EnumProtocolsA(ptr ptr ptr) EnumProtocolsA
+1112 stdcall EnumProtocolsW(ptr ptr ptr) EnumProtocolsW
 #1113 stub GetTypeByNameA
 #1114 stub GetTypeByNameW
 #1115 stub GetNameByTypeA
diff --git a/include/Makefile.in b/include/Makefile.in
index 648603b..372980f 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -41,6 +41,7 @@
 	mmsystem.h \
 	msacm.h \
 	msacmdlg.h \
+	nspapi.h \
 	ntsecapi.h \
 	oaidl.h \
 	objbase.h \
@@ -144,6 +145,8 @@
 	winver.h \
 	wnaspi32.h \
 	wownt32.h \
+	wshisotp.h \
+	wsipx.h \
 	wtypes.h \
 	zmouse.h
 
diff --git a/include/nspapi.h b/include/nspapi.h
new file mode 100644
index 0000000..e83447f
--- /dev/null
+++ b/include/nspapi.h
@@ -0,0 +1,69 @@
+/* NSPAPI.H -- winsock 1.1
+ * not supported on win95
+ */
+
+#ifndef _WINE_NSPAPI_
+#define _WINE_NSPAPI_
+
+#include "windef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* defined(__cplusplus) */
+/*
+ * constants
+ */
+#define XP_CONNECTIONLESS		0x00000001
+#define XP_GUARANTEED_DELIVERY		0x00000002
+#define XP_GUARANTEED_ORDER		0x00000004
+#define XP_MESSAGE_ORIENTED		0x00000008
+#define XP_PSEUDO_STREAM		0x00000010
+#define XP_GRACEFUL_CLOSE		0x00000020
+#define XP_EXPEDITED_DATA		0x00000040
+#define XP_CONNECT_DATA			0x00000080
+#define XP_DISCONNECT_DATA		0x00000100
+#define XP_SUPPORTS_BROADCAST		0x00000200
+#define XP_SUPPORTS_MULTICAST		0x00000400
+#define XP_BANDWITH_ALLOCATION		0x00000800
+#define XP_FRAGMENTATION		0x00001000
+#define XP_ENCRYPTS			0x00002000
+
+/*
+ * structures
+ */
+typedef  struct _PROTOCOL_INFOA 
+{
+         DWORD   dwServiceFlags;
+         INT     iAddressFamily;
+         INT     iMaxSockAddr;
+         INT     iMinSockAddr;
+         INT     iSocketType;
+         INT     iProtocol;
+         DWORD   dwMessageSize;
+         LPSTR   lpProtocol;
+} PROTOCOL_INFOA;
+
+typedef  struct _PROTOCOL_INFOW 
+{
+         DWORD   dwServiceFlags;
+         INT     iAddressFamily;
+         INT     iMaxSockAddr;
+         INT     iMinSockAddr;
+         INT     iSocketType;
+         INT     iProtocol;
+         DWORD   dwMessageSize;
+         LPWSTR  lpProtocol;
+} PROTOCOL_INFOW;
+
+
+/*
+ * function prototypes
+ */
+
+
+
+#ifdef __cplusplus
+}      /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* _WINE_NSPAPI_ */
diff --git a/include/wshisotp.h b/include/wshisotp.h
new file mode 100644
index 0000000..1387c78
--- /dev/null
+++ b/include/wshisotp.h
@@ -0,0 +1,22 @@
+/* WSHISOTP.H
+ */
+
+#ifndef _WINE_WSHISOTP_
+#define _WINE_WSHISOTP_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+/*
+ * constants
+ */
+#define ISOPROTO_TP4       29
+#define ISOPROTO_TP        ISOPROTO_TP4
+
+
+#ifdef __cplusplus
+}      /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* _WINE_WSHISOTP_ */
diff --git a/include/wsipx.h b/include/wsipx.h
new file mode 100644
index 0000000..d40839a
--- /dev/null
+++ b/include/wsipx.h
@@ -0,0 +1,23 @@
+/* WCIPX.H
+ */
+
+#ifndef _WINE_WCIPX_
+#define _WINE_WCIPX_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+/*
+ * constants
+ */
+#define NSPROTO_IPX      1000
+#define NSPROTO_SPX      1256
+#define NSPROTO_SPXII    1257
+
+
+#ifdef __cplusplus
+}      /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* _WINE_WCIPX_ */