- Add the ws2_32 library from Alex's old network branch which is a _huge_ improvement...
authorGed Murphy <gedmurphy@reactos.org>
Wed, 29 Apr 2009 18:49:47 +0000 (18:49 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Wed, 29 Apr 2009 18:49:47 +0000 (18:49 +0000)
- I've made various changes and tweaks to get it building with gcc, however it doesn't yet build with out build environment as out headers are severely lacking. It's also reliant on other winsock libs which will come in future commits along with the header rewrite.

svn path=/trunk/; revision=40738

41 files changed:
reactos/dll/win32/ws2_32_new/inc/ws2_32.h [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/inc/ws2_32p.h [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/addrconv.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/addrinfo.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/async.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/bhook.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dcatalog.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dcatitem.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dllmain.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dprocess.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dprovide.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dsocket.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dthread.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/dupsock.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/enumprot.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/event.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/getproto.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/getxbyxx.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/ioctl.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/nscatalo.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/nscatent.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/nspinstl.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/nsprovid.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/nsquery.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/qos.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/qshelpr.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/rasdial.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/recv.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/rnr.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/scihlpr.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/select.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/send.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/sockctrl.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/socklife.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/spinstal.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/sputil.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/startup.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/src/wsautil.c [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/ws2_32.def [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/ws2_32.rbuild [new file with mode: 0644]
reactos/dll/win32/ws2_32_new/ws2_32.rc [new file with mode: 0644]

diff --git a/reactos/dll/win32/ws2_32_new/inc/ws2_32.h b/reactos/dll/win32/ws2_32_new/inc/ws2_32.h
new file mode 100644 (file)
index 0000000..ca7b53a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2.2 Library
+ * FILE:        lib/ws2_32.h
+ * PURPOSE:     WinSock 2.2 Main Header
+ */
+
+#ifndef __WS2_32_H
+#define __WS2_32_H
+
+/* Definitions for NDK Usage */
+#define WIN32_NO_STATUS
+//#define _WIN32_WINNT 0x502
+#define NTOS_MODE_USER
+#define _CRT_SECURE_NO_DEPRECATE
+#define WINSOCK_API_LINKAGE
+#define DBG 1
+
+/* C Header */
+#include <stdio.h>
+
+/* PSDK and NDK Headers */
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <Ws2spi.h>
+#include <ndk/umtypes.h>
+#include <ndk/rtlfuncs.h>
+
+/* Shared NSP Headers */
+#include <nsp_dns.h>
+
+/* Winsock Helper Header */
+#include <ws2help.h>
+
+/* Missing definitions */
+#define SO_OPENTYPE                 0x7008
+#define SO_SYNCHRONOUS_NONALERT     0x20
+
+/* Internal headers */
+#include "ws2_32p.h"
+
+#endif
+
diff --git a/reactos/dll/win32/ws2_32_new/inc/ws2_32p.h b/reactos/dll/win32/ws2_32_new/inc/ws2_32p.h
new file mode 100644 (file)
index 0000000..a282885
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2.2 Library
+ * FILE:        lib/ws2_32.h
+ * PURPOSE:     WinSock 2.2 Main Header
+ */
+
+#ifndef __WS2_32P_H
+#define __WS2_32P_H
+
+#define WINSOCK_ROOT "System\\CurrentControlSet\\Services\\WinSock2\\Parameters"
+#define MAXALIASES 35
+
+typedef enum _WSASYNCOPS
+{
+    WsAsyncGetHostByAddr,
+    WsAsyncGetHostByName,
+    WsAsyncGetProtoByName,
+    WsAsyncGetProtoByNumber,
+    WsAsyncGetServByName,
+    WsAsyncGetServByPort,
+    WsAsyncTerminate,
+} WSASYNCOPS;
+
+typedef struct _WSASYNCBLOCK
+{
+    LIST_ENTRY AsyncQueue;
+    HANDLE TaskHandle;
+    WSASYNCOPS Operation;
+    union
+    {
+        struct
+        {
+            HWND hWnd;
+            UINT wMsg;
+            PCHAR ByWhat;
+            DWORD Length;
+            DWORD Type;
+            PVOID Buffer;
+            DWORD BufferLength;
+        } GetHost;
+        struct
+        {
+            HWND hWnd;
+            UINT wMsg;
+            PCHAR ByWhat;
+            DWORD Length;
+            PVOID Buffer;
+            DWORD BufferLength;
+        } GetProto;
+        struct
+        {
+            HWND hWnd;
+            UINT wMsg;
+            PCHAR ByWhat;
+            DWORD Length;
+            PCHAR Protocol;
+            PVOID Buffer;
+            DWORD BufferLength;
+        } GetServ;
+    };
+} WSASYNCBLOCK, *PWSASYNCBLOCK;
+
+typedef struct _WSASYNCCONTEXT
+{
+    LIST_ENTRY AsyncQueue;
+    HANDLE AsyncEvent;
+    LIST_ENTRY SocketList;
+} WSASYNCCONTEXT, *PWSASYNCCONTEXT;
+
+typedef struct _WSPROTO_BUFFER
+{
+    PROTOENT Protoent;
+    PCHAR Aliases[MAXALIASES];
+    CHAR LineBuffer[512];
+} WSPROTO_BUFFER, *PWSPROTO_BUFFER;
+
+typedef struct _TPROVIDER
+{
+    LONG RefCount;
+    WSPPROC_TABLE Service;
+    HINSTANCE DllHandle;
+} TPROVIDER, *PTPROVIDER;
+
+typedef struct _TCATALOG_ENTRY
+{
+    LIST_ENTRY CatalogLink;
+    LONG RefCount;
+    PTPROVIDER Provider;
+    CHAR DllPath[MAX_PATH];
+    WSAPROTOCOL_INFOW ProtocolInfo;
+} TCATALOG_ENTRY, *PTCATALOG_ENTRY;
+
+typedef struct _TCATALOG
+{
+    LIST_ENTRY ProtocolList;
+    DWORD ItemCount;
+    DWORD UniqueId;
+    DWORD NextId;
+    HKEY CatalogKey;
+    RTL_CRITICAL_SECTION Lock;
+    BOOLEAN Initialized;
+} TCATALOG, *PTCATALOG;
+
+typedef struct _NSPROVIDER
+{
+    LONG RefCount;
+    DWORD NamespaceId;
+    HINSTANCE DllHandle;
+    GUID ProviderId;
+    NSP_ROUTINE Service;
+} NSPROVIDER, *PNS_PROVIDER;
+
+typedef struct _NSQUERY_PROVIDER
+{
+    LIST_ENTRY QueryLink;
+    PNS_PROVIDER Provider;
+    HANDLE LookupHandle;
+} NSQUERY_PROVIDER, *PNSQUERY_PROVIDER;
+
+typedef struct _NSCATALOG_ENTRY
+{
+    LIST_ENTRY CatalogLink;
+    LONG RefCount;
+    PNS_PROVIDER Provider;
+    LONG AddressFamily;
+    DWORD NamespaceId;
+    DWORD Version;
+    LPWSTR ProviderName;
+    BOOLEAN Enabled;
+    BOOLEAN StoresServiceClassInfo;
+    GUID ProviderId;
+    WCHAR DllPath[MAX_PATH];
+} NSCATALOG_ENTRY, *PNSCATALOG_ENTRY;
+
+typedef struct _NSCATALOG
+{
+    LIST_ENTRY CatalogList;
+    DWORD ItemCount;
+    DWORD UniqueId;
+    HKEY CatalogKey;
+    RTL_CRITICAL_SECTION Lock;
+} NSCATALOG, *PNSCATALOG;
+
+typedef struct _NSQUERY
+{
+    DWORD Signature;
+    LONG RefCount;
+    BOOLEAN ShuttingDown;
+    LIST_ENTRY ProviderList;
+    PNSQUERY_PROVIDER ActiveProvider;
+    RTL_CRITICAL_SECTION Lock;
+    PNSQUERY_PROVIDER CurrentProvider;
+    LPWSAQUERYSETW QuerySet;
+    DWORD ControlFlags;
+    PNSCATALOG Catalog;
+    DWORD TryAgain;
+} NSQUERY, *PNSQUERY;
+
+typedef struct _WSPROCESS
+{
+    LONG RefCount;
+    HANDLE ApcHelper;
+    HANDLE HandleHelper;
+    HANDLE NotificationHelper;
+    PTCATALOG ProtocolCatalog;
+    PNSCATALOG NamespaceCatalog;
+    HANDLE ProtocolCatalogEvent;
+    HANDLE NamespaceCatalogEvent;
+    DWORD Version;
+    BOOLEAN LockReady;
+    RTL_CRITICAL_SECTION ThreadLock;
+} WSPROCESS, *PWSPROCESS;
+
+typedef struct _WSTHREAD
+{
+    PWSPROCESS Process;
+    WSATHREADID WahThreadId;
+    HANDLE AsyncHelper;
+    LPWSPCANCELBLOCKINGCALL CancelBlockingCall;
+    LPBLOCKINGCALLBACK BlockingCallback;
+    FARPROC BlockingHook;
+    BOOLEAN Blocking;
+    BOOLEAN Cancelled;
+    CHAR Buffer[32];
+    PCHAR Hostent;
+    PCHAR Servent;
+    DWORD HostentSize;
+    DWORD ServentSize;
+    DWORD OpenType;
+    PVOID ProtocolInfo;
+} WSTHREAD, *PWSTHREAD;
+
+typedef struct _WSSOCKET
+{
+   LONG RefCount;
+   HANDLE Handle;
+   PWSPROCESS Process;
+   PTPROVIDER Provider;
+   PTCATALOG_ENTRY CatalogEntry;
+   BOOLEAN Overlapped;
+   BOOLEAN ApiSocket;
+   BOOLEAN IsProvider;
+} WSSOCKET, *PWSSOCKET;
+
+typedef struct _ENUM_CONTEXT
+{
+   LPWSAQUERYSETW lpqsRestrictions;
+   INT ErrorCode;
+   PNSQUERY NsQuery;
+   PNSCATALOG Catalog;
+} ENUM_CONTEXT, *PENUM_CONTEXT;
+
+typedef struct _PROTOCOL_ENUM_CONTEXT
+{
+    LPINT Protocols;
+    LPWSAPROTOCOL_INFOW ProtocolBuffer;
+    DWORD BufferLength;
+    DWORD BufferUsed;
+    DWORD Count;
+    INT ErrorCode;
+} PROTOCOL_ENUM_CONTEXT, *PPROTOCOL_ENUM_CONTEXT;
+
+typedef struct _WS_BUFFER
+{
+    ULONG_PTR Position;
+    SIZE_T MaxSize;
+    SIZE_T BytesUsed;
+} WS_BUFFER, *PWS_BUFFER;
+
+typedef BOOL
+(WINAPI *PNSCATALOG_ENUMERATE_PROC)(
+    IN PVOID Context,
+    IN PNSCATALOG_ENTRY Entry
+);
+
+typedef BOOL
+(WINAPI *PTCATALOG_ENUMERATE_PROC)(
+    IN PVOID Context,
+    IN PTCATALOG_ENTRY Entry
+);
+
+typedef BOOL
+(WINAPI *PWS_SOCK_POST_ROUTINE)(
+    IN HWND hWnd,
+    IN UINT wMsg,
+    IN WPARAM wParam,
+    IN LPARAM lParam
+);
+
+extern HINSTANCE WsDllHandle;
+extern HANDLE WsSockHeap;
+extern PWAH_HANDLE_TABLE WsSockHandleTable;
+extern DWORD TlsIndex;
+extern PWSPROCESS CurrentWsProcess;
+extern DWORD GlobalTlsIndex;
+extern BOOLEAN WsAsyncThreadInitialized;
+extern PWS_SOCK_POST_ROUTINE WsSockPostRoutine;
+
+LPSTR
+WSAAPI
+AnsiDupFromUnicode(IN LPWSTR UnicodeString);
+
+LPWSTR
+WSAAPI
+UnicodeDupFromAnsi(IN LPSTR AnsiString);
+
+VOID
+WSAAPI
+WsRasInitializeAutodial(VOID);
+
+VOID
+WSAAPI
+WsRasUninitializeAutodial(VOID);
+
+BOOL
+WSAAPI
+WSAttemptAutodialName(IN CONST LPWSAQUERYSETW lpqsRestrictions);
+
+BOOL
+WSAAPI
+WSAttemptAutodialAddr(
+    IN CONST SOCKADDR FAR *Name,
+    IN INT NameLength
+);
+
+VOID
+WSAAPI
+WSNoteSuccessfulHostentLookup(
+    IN CONST CHAR FAR *Name,
+    IN CONST ULONG Address
+);
+
+INT
+WSAAPI
+MapUnicodeProtocolInfoToAnsi(IN LPWSAPROTOCOL_INFOW UnicodeInfo,
+                             OUT LPWSAPROTOCOL_INFOA AnsiInfo);
+
+INT
+WSAAPI
+MapAnsiQuerySetToUnicode(IN LPWSAQUERYSETA AnsiSet,
+                         IN OUT PSIZE_T SetSize,
+                         OUT LPWSAQUERYSETW UnicodeSet);
+
+INT
+WSAAPI
+MapUnicodeQuerySetToAnsi(OUT LPWSAQUERYSETW UnicodeSet,
+                         IN OUT PSIZE_T SetSize,
+                         IN LPWSAQUERYSETA AnsiSet);
+
+INT
+WSAAPI
+CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet,
+              OUT LPWSAQUERYSETW *UnicodeCopy);
+
+INT
+WSAAPI
+WsSlowProlog(VOID);
+
+INT
+WSAAPI
+WsSlowPrologTid(OUT LPWSATHREADID *ThreadId);
+
+PWSSOCKET
+WSAAPI
+WsSockGetSocket(IN SOCKET Handle);
+
+INT
+WSAAPI
+WsApiProlog(OUT PWSPROCESS *Process,
+            OUT PWSTHREAD *Thread);
+
+HKEY
+WSAAPI
+WsOpenRegistryRoot(VOID);
+
+VOID
+WSAAPI
+WsCreateStartupSynchronization(VOID);
+
+VOID
+WSAAPI
+WsDestroyStartupSynchronization(VOID);
+
+INT
+WSAAPI
+WsSetupCatalogProtection(IN HKEY CatalogKey,
+                         IN HANDLE CatalogEvent,
+                         OUT LPDWORD UniqueId);
+
+BOOL
+WSAAPI
+WsCheckCatalogState(IN HANDLE Event);
+
+PNSCATALOG
+WSAAPI
+WsNcAllocate(VOID);
+
+VOID
+WSAAPI
+WsNcDelete(IN PNSCATALOG Catalog);
+
+INT
+WSAAPI
+WsNcInitializeFromRegistry(IN PNSCATALOG Catalog,
+                           IN HKEY ParentKey,
+                           IN HANDLE CatalogEvent);
+
+INT
+WSAAPI
+WsNcRefreshFromRegistry(IN PNSCATALOG Catalog,
+                        IN HANDLE CatalogEvent);
+
+VOID
+WSAAPI
+WsNcUpdateNamespaceList(IN PNSCATALOG Catalog,
+                        IN PLIST_ENTRY List);
+
+BOOL
+WSAAPI
+WsNcMatchProtocols(IN DWORD NameSpace,
+                   IN LONG AddressFamily,
+                   IN LPWSAQUERYSETW QuerySet);
+
+INT
+WSAAPI
+WsNcLoadProvider(IN PNSCATALOG Catalog,
+                 IN PNSCATALOG_ENTRY CatalogEntry);
+
+INT
+WSAAPI
+WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog,
+                             IN LPGUID ProviderId,
+                             OUT PNSCATALOG_ENTRY *CatalogEntry);
+
+VOID
+WSAAPI
+WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog,
+                          IN PNSCATALOG_ENUMERATE_PROC Callback,
+                          IN PVOID Context);
+
+INT
+WSAAPI
+WsNcGetServiceClassInfo(IN PNSCATALOG Catalog,
+                        IN OUT LPDWORD BugSize,
+                        IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo);
+
+PNSCATALOG_ENTRY
+WSAAPI
+WsNcEntryAllocate(VOID);
+
+INT
+WSAAPI
+WsNcEntryInitializeFromRegistry(IN PNSCATALOG_ENTRY CatalogEntry,
+                                IN HKEY ParentKey,
+                                IN ULONG UniqueId);
+
+VOID
+WSAAPI
+WsNcEntryDereference(IN PNSCATALOG_ENTRY CatalogEntry);
+
+VOID
+WSAAPI
+WsNcEntrySetProvider(IN PNSCATALOG_ENTRY Entry,
+                     IN PNS_PROVIDER Provider);
+
+DWORD
+WSAAPI
+WsNqAddProvider(
+    IN PNSQUERY NsQuery,
+    IN PNS_PROVIDER Provider
+);
+
+PNSQUERY
+WSAAPI
+WsNqAllocate(VOID);
+
+BOOL
+WSAAPI
+WsNqBeginEnumerationProc(
+    PVOID Context,
+    PNSCATALOG_ENTRY CatalogEntry
+);
+
+VOID
+WSAAPI
+WsNqDelete(IN PNSQUERY NsQuery);
+
+DWORD
+WSAAPI
+WsNqInitialize(IN PNSQUERY NsQuery);
+
+DWORD
+WSAAPI
+WsNqLookupServiceBegin(
+    IN PNSQUERY NsQuery,
+    IN LPWSAQUERYSETW QuerySet,
+    IN DWORD ControlFlags,
+    IN PNSCATALOG Catalog
+);
+
+DWORD
+WSAAPI
+WsNqLookupServiceEnd(IN PNSQUERY NsQuery);
+
+DWORD
+WSAAPI
+WsNqLookupServiceNext(
+    PNSQUERY NsQuery,
+    DWORD,
+    PDWORD,
+    OUT LPWSAQUERYSETW QuerySet
+);
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqNextProvider(
+    PNSQUERY NsQuery,
+    IN PNSQUERY_PROVIDER Provider
+);
+
+VOID
+WSAAPI
+WsNqDereference(IN PNSQUERY Query);
+
+BOOL
+WSAAPI
+WsNqValidateAndReference(IN PNSQUERY Query);
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqPreviousProvider(IN PNSQUERY Query,
+                     IN PNSQUERY_PROVIDER Provider);
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceNext(
+    IN PNSQUERY_PROVIDER QueryProvider,
+    DWORD,
+    PDWORD ,
+    LPWSAQUERYSETW QuerySet
+);
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceEnd(IN PNSQUERY_PROVIDER QueryProvider);
+
+DWORD
+WSAAPI
+WsNqProvInitialize(
+    IN PNSQUERY_PROVIDER QueryProvider,
+    IN PNS_PROVIDER Provider
+);
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqProvAllocate(VOID);
+
+VOID
+WSAAPI
+WsNqProvDelete(IN PNSQUERY_PROVIDER QueryProvider);
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceBegin(
+    IN PNSQUERY_PROVIDER QueryProvider,
+    IN LPWSAQUERYSETW QuerySet,
+    IN LPWSASERVICECLASSINFOW ServiceClassInfo,
+    IN DWORD 
+);
+
+VOID
+WSAAPI
+WsNpDelete(IN PNS_PROVIDER Provider);
+
+DWORD
+WSAAPI
+WsNpLookupServiceBegin (
+    IN PNS_PROVIDER Provider,
+    IN LPWSAQUERYSETW Restrictions,
+    struct _WSAServiceClassInfoW *,
+    IN DWORD ControlFlags,
+    OUT PHANDLE LookupHandle
+);
+
+DWORD
+WSAAPI
+WsNpNSPCleanup(IN PNS_PROVIDER Provider);
+
+DWORD
+WSAAPI
+WsNpLookupServiceEnd(
+    IN PNS_PROVIDER Provider,
+    IN HANDLE LookupHandle
+);
+
+DWORD
+WSAAPI
+WsNpInitialize(
+    IN PNS_PROVIDER Provider,
+    IN LPWSTR DllPath,
+    IN LPGUID ProviderGuid
+);
+
+PNS_PROVIDER
+WSAAPI
+WsNpAllocate(VOID);
+
+VOID
+WSAAPI
+WsNpDereference(IN PNS_PROVIDER Provider);
+
+DWORD
+WSAAPI
+WsNpLookupServiceNext(
+    IN PNS_PROVIDER Provider,
+    IN HANDLE LookupHandle,
+    IN DWORD ControlFlags,
+    OUT PDWORD BufferLength,
+    OUT LPWSAQUERYSETW Results
+);
+
+VOID
+WSAAPI
+WsTpDelete(IN PTPROVIDER Provider);
+
+DWORD
+WSAAPI
+WsTpWSPCleanup(
+    IN PTPROVIDER Provider,
+    int *
+);
+
+PTPROVIDER
+WSAAPI
+WsTpAllocate(VOID);
+
+DWORD
+WSAAPI
+WsTpInitialize(
+    IN PTPROVIDER Provider,
+    IN LPSTR DllName,
+    LPWSAPROTOCOL_INFOW ProtocolInfo
+);
+
+VOID
+WSAAPI
+WsTpDereference(IN PTPROVIDER Provider);
+
+VOID
+WSAAPI
+WsThreadDelete(IN PWSTHREAD Thread);
+
+VOID
+WSAAPI
+WsThreadDestroyCurrentThread(VOID);
+
+DWORD
+WSAAPI
+WsThreadCreate(
+    IN PWSPROCESS Process,
+    IN PWSTHREAD *Thread
+);
+
+DWORD
+WSAAPI
+WsThreadGetCurrentThread(
+    IN PWSPROCESS Process,
+    IN PWSTHREAD *Thread
+);
+
+LPWSATHREADID
+WSAAPI
+WsThreadGetThreadId(IN PWSPROCESS Process);
+
+DWORD
+WSAAPI
+WsThreadStartup(VOID);
+
+VOID
+WSAAPI
+WsThreadCleanup(VOID);
+
+DWORD
+WSAAPI
+WsThreadCancelBlockingCall(IN PWSTHREAD Thread);
+
+DWORD
+WSAAPI
+WsThreadUnhookBlockingHook(IN PWSTHREAD Thread);
+
+FARPROC
+WSAAPI
+WsThreadSetBlockingHook(IN PWSTHREAD Thread,
+                        IN FARPROC BlockingHook);
+
+
+PHOSTENT
+WSAAPI
+WsThreadBlobToHostent(IN PWSTHREAD Thread,
+                      IN LPBLOB Blob);
+
+PSERVENT
+WSAAPI
+WsThreadBlobToServent(IN PWSTHREAD Thread,
+                      IN LPBLOB Blob);
+
+PWSPROTO_BUFFER
+WSAAPI
+WsThreadGetProtoBuffer(IN PWSTHREAD Thread);
+
+PWSTHREAD
+WSAAPI
+WsThreadAllocate(VOID);
+
+DWORD
+WSAAPI
+WsThreadDefaultBlockingHook(VOID);
+
+DWORD
+WSAAPI
+WsThreadInitialize(
+    IN PWSTHREAD Thread,
+    IN PWSPROCESS Process
+);
+
+DWORD
+WSAAPI
+WsTcFindIfsProviderForSocket(IN PTCATALOG TCatalog, SOCKET Socket);
+
+DWORD
+WSAAPI
+WsTcEntryInitializeFromRegistry(IN PTCATALOG_ENTRY CatalogEntry, IN HKEY, unsigned long);
+
+DWORD
+WSAAPI
+WsTcGetEntryFromAf(IN PTCATALOG TCatalog, IN INT AddressFamily, IN PTCATALOG_ENTRY *CatalogEntry);
+
+PTCATALOG_ENTRY
+WSAAPI
+WsTcEntryAllocate(VOID);
+
+VOID
+WSAAPI
+WsTcEntrySetProvider(IN PTCATALOG_ENTRY CatalogEntry, IN PTPROVIDER Provider);
+
+DWORD
+WSAAPI
+WsTcRefreshFromRegistry(IN PTCATALOG TCatalog, PVOID);
+
+BOOL
+WSAAPI
+WsTcOpen(IN PTCATALOG TCatalog, IN HKEY);
+
+PTPROVIDER
+WSAAPI
+WsTcFindProvider(IN PTCATALOG TCatalog, IN LPGUID ProviderId);
+
+VOID
+WSAAPI
+WsTcEnumerateCatalogItems(IN PTCATALOG Catalog,
+                          IN PTCATALOG_ENUMERATE_PROC Callback,
+                          IN PVOID Context);
+
+VOID
+WSAAPI
+WsTcEntryDereference(IN PTCATALOG_ENTRY CatalogEntry);
+
+PTCATALOG
+WSAAPI
+WsTcAllocate(VOID);
+
+VOID
+WSAAPI
+WsTcDelete(IN PTCATALOG Catalog);
+
+DWORD
+WSAAPI
+WsTcGetEntryFromTriplet(IN PTCATALOG TCatalog, IN INT AddressFamily, IN INT SocketType, IN INT Protocol, IN DWORD StartId, IN PTCATALOG_ENTRY *CatalogEntry);
+
+VOID
+WSAAPI
+WsTcUpdateProtocolList(IN PTCATALOG TCatalog, PLIST_ENTRY ProtocolList);
+
+VOID
+WSAAPI
+WsTcEntryDelete(IN PTCATALOG_ENTRY CatalogEntry);
+
+DWORD
+WSAAPI
+WsTcGetEntryFromCatalogEntryId(IN PTCATALOG TCatalog, IN DWORD CatalogEntryId, IN PTCATALOG_ENTRY *CatalogEntry);
+
+DWORD
+WSAAPI
+WsTcLoadProvider(IN PTCATALOG TCatalog, IN PTCATALOG_ENTRY CatalogEntry);
+
+DWORD
+WSAAPI
+WsTcInitializeFromRegistry(IN PTCATALOG TCatalog, HKEY, PVOID);
+
+INT
+WSAAPI
+WsSockStartup(VOID);
+
+VOID
+WSAAPI
+WsSockCleanup(VOID);
+
+BOOL
+WSAAPI
+WsSockDeleteSockets(IN LPVOID Context,
+                    IN PWAH_HANDLE Handle);
+
+VOID
+WSAAPI
+WsSockDereference(IN PWSSOCKET Socket);
+
+PWSSOCKET
+WSAAPI
+WsSockAllocate(VOID);
+
+INT
+WSAAPI
+WsSockInitialize(IN PWSSOCKET Socket,
+                 IN PTCATALOG_ENTRY CatalogEntry);
+
+INT
+WSAAPI
+WsSockAssociateHandle(IN PWSSOCKET Socket,
+                      IN SOCKET Handle,
+                      IN BOOLEAN IsProvider);
+
+INT
+WSAAPI
+WsSockDisassociateHandle(IN PWSSOCKET Socket);
+
+INT
+WSAAPI
+WsSockAddApiReference(IN SOCKET Handle);
+
+PTCATALOG
+WSAAPI
+WsProcGetTCatalog(IN PWSPROCESS Process);
+
+BOOL
+WSAAPI
+WsProcDetachSocket(IN PWSPROCESS Process,
+                   IN PWAH_HANDLE Handle);
+
+INT
+WSAAPI
+WsProcGetAsyncHelper(IN PWSPROCESS Process,
+                     OUT PHANDLE Handle);
+
+VOID
+WSAAPI
+WsProcDelete(IN PWSPROCESS Process);
+
+INT
+WSAAPI
+WsProcStartup(VOID);
+
+PNSCATALOG
+WSAAPI
+WsProcGetNsCatalog(IN PWSPROCESS Process);
+
+VOID
+WSAAPI
+WsProcSetVersion(IN PWSPROCESS Process,
+                 IN WORD VersionRequested);
+
+VOID
+WSAAPI
+WsAsyncQueueRequest(IN PWSASYNCBLOCK AsyncBlock);
+
+BOOL
+WSAAPI
+WsAsyncCheckAndInitThread(VOID);
+
+INT
+WSAAPI
+WsAsyncCancelRequest(IN HANDLE TaskHandle);
+
+PWSASYNCBLOCK
+WSAAPI
+WsAsyncAllocateBlock(IN SIZE_T ExtraLength);
+
+VOID
+WSAAPI
+WsAsyncTerminateThread(VOID);
+
+VOID
+WSAAPI
+WsAsyncGlobalTerminate(VOID);
+
+VOID
+WSAAPI
+WsAsyncGlobalInitialize(VOID);
+
+FORCEINLINE
+PWSPROCESS
+WsGetProcess()
+{
+    return CurrentWsProcess;
+}
+
+FORCEINLINE
+DWORD
+WsQuickProlog()
+{
+    /* Try to see if we're initialized. If not, do the full prolog */
+    return WsGetProcess() ? ERROR_SUCCESS : WsSlowProlog();
+}
+
+FORCEINLINE
+DWORD
+WsQuickPrologTid(LPWSATHREADID *Tid)
+{
+    /* Try to see if we're initialized. If not, do the full prolog */
+    if ((WsGetProcess()) && (*Tid = WsThreadGetThreadId(WsGetProcess())))
+    {
+        return ERROR_SUCCESS;
+    }
+    else
+    {
+        return WsSlowPrologTid(Tid);
+    }
+}
+
+#endif
+
diff --git a/reactos/dll/win32/ws2_32_new/src/addrconv.c b/reactos/dll/win32/ws2_32_new/src/addrconv.c
new file mode 100644 (file)
index 0000000..021c209
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        addrconv.c
+ * PURPOSE:     Address and Port Conversion Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+     
+/* DEFINES *******************************************************************/
+
+#ifndef BE
+
+/* DWORD network to host byte order conversion for little endian machines */
+#define DN2H(dw) \
+  ((((dw) & 0xFF000000L) >> 24) | \
+   (((dw) & 0x00FF0000L) >> 8) | \
+     (((dw) & 0x0000FF00L) << 8) | \
+     (((dw) & 0x000000FFL) << 24))
+
+/* DWORD host to network byte order conversion for little endian machines */
+#define DH2N(dw) \
+    ((((dw) & 0xFF000000L) >> 24) | \
+     (((dw) & 0x00FF0000L) >> 8) | \
+     (((dw) & 0x0000FF00L) << 8) | \
+     (((dw) & 0x000000FFL) << 24))
+
+/* WORD network to host order conversion for little endian machines */
+#define WN2H(w) \
+    ((((w) & 0xFF00) >> 8) | \
+     (((w) & 0x00FF) << 8))
+
+/* WORD host to network byte order conversion for little endian machines */
+#define WH2N(w) \
+    ((((w) & 0xFF00) >> 8) | \
+     (((w) & 0x00FF) << 8))
+
+#else /* BE */
+
+/* DWORD network to host byte order conversion for big endian machines */
+#define DN2H(dw) \
+    (dw)
+
+/* DWORD host to network byte order conversion big endian machines */
+#define DH2N(dw) \
+    (dw)
+
+/* WORD network to host order conversion for big endian machines */
+#define WN2H(w) \
+    (w)
+
+/* WORD host to network byte order conversion for big endian machines */
+#define WH2N(w) \
+    (w)
+
+#endif /* BE */
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+ULONG
+WSAAPI
+inet_addr(IN  CONST CHAR FAR* cp)
+{
+    register u_long val, base, n;
+    register unsigned char c;
+    u_long parts[4], *pp = parts;
+
+again:
+    /*
+     * Collect number up to ``.''.
+     * Values are specified as for C:
+     * 0x=hex, 0=octal, other=decimal.
+     */
+    val = 0; base = 10;
+    if (*cp == '0') {
+        if (*++cp == 'x' || *cp == 'X')
+            base = 16, cp++;
+        else
+            base = 8;
+    }
+    while ((c = *cp)) {
+        if (isdigit(c)) {
+            val = (val * base) + (c - '0');
+            cp++;
+            continue;
+        }
+        if (base == 16 && isxdigit(c)) {
+            val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+            cp++;
+            continue;
+        }
+        break;
+    }
+    if (*cp == '.') {
+        /*
+         * Internet format:
+         *    a.b.c.d
+         *    a.b.c    (with c treated as 16-bits)
+         *    a.b    (with b treated as 24 bits)
+         */
+        if (pp >= parts + 4) return (INADDR_NONE);
+        *pp++ = val;
+        cp++;
+        goto again;
+    }
+    /*
+     * Check for trailing characters.
+     */
+    if (*cp && !isspace((UCHAR)*cp)) return (INADDR_NONE);
+
+    *pp++ = val;
+    /*
+     * Concoct the address according to
+     * the number of parts specified.
+     */
+    n = (u_long)(pp - parts);
+    switch (n) {
+
+    case 1:                /* a -- 32 bits */
+        val = parts[0];
+        break;
+
+    case 2:                /* a.b -- 8.24 bits */
+        val = (parts[0] << 24) | (parts[1] & 0xffffff);
+        break;
+
+    case 3:                /* a.b.c -- 8.8.16 bits */
+        val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
+            (parts[2] & 0xffff);
+        break;
+
+    case 4:                /* a.b.c.d -- 8.8.8.8 bits */
+        val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
+              ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
+        break;
+
+    default:
+        return (-1);
+    }
+    val = htonl(val);
+    return (val);
+}
+
+/*
+ * @implemented
+ */
+CHAR FAR*
+WSAAPI
+inet_ntoa(IN IN_ADDR in)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    WSADATA WsaData;
+    BOOL ManualLoad = FALSE;
+    CHAR b[10];
+    PCHAR p;
+    DPRINT("inet_ntoa: %lx\n", in);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        DPRINT("MANUAL LOAD\n");
+
+        /* Only fail if the error wasn't related to a missing WSAStartup */
+        if (ErrorCode != WSANOTINITIALISED)
+        {
+            /* Fail */
+            SetLastError(ErrorCode);
+            return NULL;
+        }
+
+        /* Apps aren't expected to call WSAStartup for this API, so we will */
+        if ((ErrorCode = WSAStartup(MAKEWORD(2,2), &WsaData)) != ERROR_SUCCESS)
+        {
+            /* We failed */
+            SetLastError(ErrorCode);
+            return NULL;
+        }
+
+        /* Try the prolog again */
+        ManualLoad = TRUE;
+        if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+        {
+            /* Failed again... */
+            WSACleanup();
+            SetLastError(ErrorCode);
+            return NULL;
+        }
+    }
+
+    p = Thread->Buffer;
+    _itoa(in.S_un.S_addr & 0xFF, b, 10);
+    strcpy(p, b);
+    _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
+    strcat(p, ".");
+    strcat(p, b);
+    _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
+    strcat(p, ".");
+    strcat(p, b);
+    _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
+    strcat(p, ".");
+    strcat(p, b);
+
+    /* Cleanup the manual load */
+    if (ManualLoad) WSACleanup();
+
+    /* Return the buffer */
+    return p;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+WSAAPI
+htonl(IN ULONG hostlong)
+{
+    return DH2N(hostlong);
+}
+
+/*
+ * @implemented
+ */
+USHORT
+WSAAPI
+htons(IN USHORT hostshort)
+{
+    return WH2N(hostshort);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+WSAAPI
+ntohl(IN ULONG netlong)
+{
+    return DN2H(netlong);
+}
+
+/*
+ * @implemented
+ */
+USHORT
+WSAAPI
+ntohs(IN USHORT netshort)
+{
+    return WN2H(netshort);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAHtonl(IN SOCKET s,
+         IN ULONG hostlong,
+         OUT ULONG FAR* lpnetlong)
+{
+    INT ErrorCode;
+    PWSSOCKET Socket;
+    DPRINT("WSAHtonl: %p, %lx, %p\n", s, hostlong, lpnetlong);
+    
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Make sure we got a parameter */
+        if (!lpnetlong)
+        {
+            /* Fail */
+            SetLastError(WSAEFAULT);
+            return SOCKET_ERROR;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Check which byte order to use */
+            if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
+                LITTLEENDIAN)
+            {
+                /* No conversion needed */
+                *lpnetlong = hostlong;
+            }
+            else
+            {
+                /* Use a swap */
+                *lpnetlong = DN2H(hostlong);
+            }
+
+            /* Dereference the socket */
+            WsSockDereference(Socket);
+
+            /* Return success */
+            return ERROR_SUCCESS;
+        }
+        else
+        {
+            /* Set the error code */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAHtons(IN SOCKET s,
+         IN USHORT hostshort,
+         OUT USHORT FAR* lpnetshort)
+{
+    INT ErrorCode;
+    PWSSOCKET Socket;
+    DPRINT("WSAHtons: %p, %lx, %p\n", s, hostshort, lpnetshort);
+    
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Make sure we got a parameter */
+        if (!lpnetshort)
+        {
+            /* Fail */
+            SetLastError(WSAEFAULT);
+            return SOCKET_ERROR;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Check which byte order to use */
+            if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
+                LITTLEENDIAN)
+            {
+                /* No conversion needed */
+                *lpnetshort = hostshort;
+            }
+            else
+            {
+                /* Use a swap */
+                *lpnetshort = WN2H(hostshort);
+            }
+
+            /* Dereference the socket */
+            WsSockDereference(Socket);
+
+            /* Return success */
+            return ERROR_SUCCESS;
+        }
+        else
+        {
+            /* Set the error code */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSANtohl(IN SOCKET s,
+         IN ULONG netlong,
+         OUT ULONG FAR* lphostlong)
+{
+    INT ErrorCode;
+    PWSSOCKET Socket;
+    DPRINT("WSANtohl: %p, %lx, %p\n", s, netlong, lphostlong);
+    
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Make sure we got a parameter */
+        if (!lphostlong)
+        {
+            /* Fail */
+            SetLastError(WSAEFAULT);
+            return SOCKET_ERROR;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Check which byte order to use */
+            if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
+                LITTLEENDIAN)
+            {
+                /* No conversion needed */
+                *lphostlong = netlong;
+            }
+            else
+            {
+                /* Use a swap */
+                *lphostlong = DN2H(netlong);
+            }
+
+            /* Dereference the socket */
+            WsSockDereference(Socket);
+
+            /* Return success */
+            return ERROR_SUCCESS;
+        }
+        else
+        {
+            /* Set the error code */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSANtohs(IN SOCKET s,
+         IN USHORT netshort,
+         OUT USHORT FAR* lphostshort)
+{
+    INT ErrorCode;
+    PWSSOCKET Socket;
+    DPRINT("WSANtohs: %p, %lx, %p\n", s, netshort, lphostshort);
+    
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Make sure we got a parameter */
+        if (!lphostshort)
+        {
+            /* Fail */
+            SetLastError(WSAEFAULT);
+            return SOCKET_ERROR;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Check which byte order to use */
+            if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
+                LITTLEENDIAN)
+            {
+                /* No conversion needed */
+                *lphostshort = netshort;
+            }
+            else
+            {
+                /* Use a swap */
+                *lphostshort = WN2H(netshort);
+            }
+
+            /* Dereference the socket */
+            WsSockDereference(Socket);
+
+            /* Return success */
+            return ERROR_SUCCESS;
+        }
+        else
+        {
+            /* Set the error code */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
diff --git a/reactos/dll/win32/ws2_32_new/src/addrinfo.c b/reactos/dll/win32/ws2_32_new/src/addrinfo.c
new file mode 100644 (file)
index 0000000..cfdb4f1
--- /dev/null
@@ -0,0 +1,986 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        addrinfo.c
+ * PURPOSE:     Protocol-Independent Address Resolution
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DEFINES *******************************************************************/
+
+#define Swap(a, b, c)       { (c) = (a); (a) = (b); (b) = (c); }
+#define FreeAddrInfoW(a)    freeaddrinfo((LPADDRINFO)a)
+
+/* FUNCTIONS *****************************************************************/
+
+/* FIXME: put into dnslib */
+VOID
+WSAAPI
+Dns_Ip4AddressToReverseName_W(IN LPWSTR AddressBuffer,
+                              IN IN_ADDR Address)
+{
+    /* Convert the address into IPv4 format */
+    wsprintfW(AddressBuffer, L"%u.%u.%u.%u.in-addr.arpa.",
+              Address.S_un.S_un_b.s_b4,
+              Address.S_un.S_un_b.s_b3,
+              Address.S_un.S_un_b.s_b2,
+              Address.S_un.S_un_b.s_b1);
+}
+
+VOID
+WINAPI
+Dns_SplitHostFromDomainNameW(IN LPWSTR DomainName)
+{
+    /* FIXME */
+}
+
+static
+INT
+WINAPI
+ConvertAddrinfoFromUnicodeToAnsi(IN PADDRINFOW Addrinfo)
+{
+    LPSTR AnsiName;
+    LPWSTR *UnicodeName;
+
+    /* Make sure we have a valid pointer */
+    if (Addrinfo)
+    {
+        do
+        {
+            /* Get the name */
+            UnicodeName = &Addrinfo->ai_canonname;
+            
+            /* Check if it exists */
+            if (*UnicodeName)
+            {
+                /* Convert it */
+                AnsiName = AnsiDupFromUnicode(*UnicodeName);
+                if (AnsiName)
+                {
+                    /* Free the old one */
+                    HeapFree(WsSockHeap, 0, *UnicodeName);
+            
+                    /* Set the new one */
+                    *UnicodeName = (LPWSTR)AnsiName;
+                }
+                else
+                {
+                    return GetLastError();
+                }
+            }
+        } while ((Addrinfo = Addrinfo->ai_next));
+    }
+
+    /* All done */
+    return ERROR_SUCCESS;
+}
+
+static
+BOOL
+WINAPI
+ParseV4Address(IN PCWSTR AddressString,
+               OUT PDWORD pAddress)
+{
+    DWORD Address;
+    LPWSTR Ip = 0;
+
+    /* Do the conversion, don't accept wildcard */
+    RtlIpv4StringToAddressW((LPWSTR)AddressString, 0, Ip, (IN_ADDR *)&Address);
+
+    /* Return the address and success */
+    *pAddress = Address;
+    return FALSE;
+}
+
+static
+PADDRINFOW
+WINAPI
+NewAddrInfo(IN INT SocketType,
+            IN INT Protocol,
+            IN WORD Port,
+            IN DWORD Address)
+{
+    PADDRINFOW AddrInfo;
+    PSOCKADDR_IN SockAddress;
+
+    /* Allocate a structure */
+    AddrInfo = HeapAlloc(WsSockHeap, 0, sizeof(ADDRINFOW));
+    if (!AddrInfo) return NULL;
+
+    /* Allocate a sockaddr */
+    SockAddress = HeapAlloc(WsSockHeap, 0, sizeof(SOCKADDR_IN));
+    if (!SockAddress)
+    {
+        /* Free the addrinfo and fail */
+        HeapFree(WsSockHeap, 0, AddrInfo);
+        return NULL;
+    }
+
+    /* Write data for socket address */
+    SockAddress->sin_family = AF_INET;
+    SockAddress->sin_port = Port;
+    SockAddress->sin_addr.s_addr = Address;
+    
+    /* Fill out the addrinfo */
+    AddrInfo->ai_family = PF_INET;
+    AddrInfo->ai_socktype = SocketType;
+    AddrInfo->ai_protocol = Protocol;
+    AddrInfo->ai_flags = 0;
+    AddrInfo->ai_next = 0;
+    AddrInfo->ai_canonname = NULL;
+    AddrInfo->ai_addrlen = sizeof(SOCKADDR_IN);
+    AddrInfo->ai_addr = (PSOCKADDR)SockAddress;
+
+    /* Return it */
+    return AddrInfo;
+}
+
+static
+INT
+WINAPI
+CloneAddrInfo(IN WORD Port,
+              IN PADDRINFOW ptResult)
+{
+    PADDRINFOW Next = NULL;
+    PADDRINFOW New  = NULL;
+
+    /* Loop the chain */
+    for (Next = ptResult; Next;)
+    {
+        /* Create a new structure */
+        New = NewAddrInfo(SOCK_DGRAM,
+                          Next->ai_protocol,
+                          Port,
+                          ((PSOCKADDR_IN)Next->ai_addr)->sin_addr.s_addr);
+        if (!New) break;
+
+        /* Link them */
+        New->ai_next = Next->ai_next;
+        Next->ai_next = New;
+        Next = New->ai_next;
+    }
+
+    /* Check if we ran out of memory */
+    if (Next) return EAI_MEMORY;
+    
+    /* Return success */
+    return 0;
+}
+
+static
+INT
+WINAPI
+QueryDNS(IN LPCSTR NodeName,
+         IN INT SocketType,
+         IN INT Protocol,
+         IN WORD Port,
+         OUT CHAR Alias[NI_MAXHOST],
+         OUT PADDRINFOW *pptResult)
+{
+    PADDRINFOW *Next = pptResult;
+    PHOSTENT Hostent = NULL;
+    PCHAR *Addresses;
+
+    /* Assume nothing found */
+    *Next = NULL;
+    Alias[0] = '\0';
+
+    /* Get the hostent */
+    Hostent = gethostbyname(NodeName);
+    if (Hostent)
+    {
+        /* Check for valid addresses */
+        if ((Hostent->h_addrtype == AF_INET) &&
+            (Hostent->h_length == sizeof(IN_ADDR)))
+        {
+            /* Loop every address in it */
+            for (Addresses = Hostent->h_addr_list; *Addresses; Addresses++)
+            {
+                /* Create an addrinfo structure for it*/
+                *Next = NewAddrInfo(SocketType,
+                                    Protocol,
+                                    Port,
+                                    ((PIN_ADDR)*Addresses)->s_addr);
+                if (!*Next) return EAI_MEMORY;
+
+                /* Move to the next entry */
+                Next = &((*Next)->ai_next);
+            }
+        }
+
+        /* Copy the canonical name */
+        strcpy(Alias, Hostent->h_name);
+        
+        /* Return success */
+        return 0;
+    }
+    
+    /* Find out what the error was */
+    switch (GetLastError())
+    {
+        /* Convert the Winsock Error to an EAI error */
+        case WSAHOST_NOT_FOUND: return EAI_NONAME;
+        case WSATRY_AGAIN: return EAI_AGAIN;
+        case WSANO_RECOVERY: return EAI_FAIL;
+        case WSANO_DATA: return EAI_NODATA;
+        default: return EAI_NONAME;
+    }
+}
+
+static
+INT
+WINAPI
+LookupNodeByAddr(IN LPWSTR pNodeBuffer,
+                 IN DWORD NodeBufferSize,
+                 IN BOOLEAN OnlyNodeName,
+                 IN PVOID Addr,
+                 IN DWORD AddrSize,
+                 IN INT AddressFamily)
+{
+    GUID LookupGuid = SVCID_DNS_TYPE_PTR;
+    PIN_ADDR Ip4Addr = Addr;
+    WCHAR ReverseBuffer[76];
+    WSAQUERYSETW Restrictions, Reply;
+    DWORD BufferLength;
+    INT ErrorCode;
+    HANDLE LookupHandle;
+
+    /* Validate the address */
+    if (!Addr) return WSAEFAULT;
+
+    /* Make sure the family and address size match */
+    if (AddressFamily == AF_INET6)
+    {
+        /* Check the address size for this type */
+        if (AddrSize != sizeof(IN6_ADDR)) return WSAEFAULT;
+        Ip4Addr = (PIN_ADDR)&((PIN6_ADDR)Addr)->u.Byte[12];
+    }
+    else if (AddressFamily == AF_INET)
+    {
+        /* Check the address size for this type */
+        if (AddrSize != sizeof(IN_ADDR)) return WSAEFAULT;
+    }
+    else
+    {
+        /* Address family not supported */
+        return WSAEAFNOSUPPORT;
+    }
+
+    /* Check if this is a mapped V4 IPv6 or pure IPv4 */
+    if (((AddressFamily == AF_INET6) && (IN6_IS_ADDR_V4MAPPED(Addr))) ||
+        (AddressFamily == AF_INET))
+    {
+        /* Get the reverse name */
+        Dns_Ip4AddressToReverseName_W(ReverseBuffer, *Ip4Addr);
+    }
+    /* FIXME: Not implemented for now 
+    else if ( */
+
+    /* By this point we have the Reverse Name, so prepare for lookup */
+    RtlZeroMemory(&Restrictions, sizeof(Restrictions));
+    Restrictions.dwSize = sizeof(Restrictions);
+    Restrictions.lpszServiceInstanceName = ReverseBuffer;
+    Restrictions.lpServiceClassId = &LookupGuid;
+    Restrictions.dwNameSpace = NS_DNS;
+
+    /* Now do the lookup */
+    ErrorCode = WSALookupServiceBeginW(&Restrictions,
+                                       LUP_RETURN_NAME,
+                                       &LookupHandle);
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Lookup succesfull, now get the data */
+        BufferLength = (NI_MAXHOST - 1) * sizeof(WCHAR) + sizeof(Restrictions);
+        ErrorCode = WSALookupServiceNextW(LookupHandle,
+                                          0,
+                                          &BufferLength,
+                                          &Restrictions);
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            /* Now check if we have a name back */
+            Reply = Restrictions;
+            if (!Reply.lpszServiceInstanceName)
+            {
+                /* Fail */
+                ErrorCode = WSAHOST_NOT_FOUND;
+            }
+            else
+            {
+                /* Check if the caller only wants the node name */
+                if (OnlyNodeName)
+                {
+                    /* Split it and get only the partial host name */
+                    Dns_SplitHostFromDomainNameW(Reply.lpszServiceInstanceName);
+                }
+
+                /* Check the length and see if it's within our limit */
+                if (wcslen(Reply.lpszServiceInstanceName) + 1 >
+                    NodeBufferSize)
+                {
+                    /* It's not, so fail */
+                    ErrorCode = WSAEFAULT;
+                }
+                else
+                {
+                    /* It will fit, let's copy it*/
+                    wcscpy(pNodeBuffer, Reply.lpszServiceInstanceName);
+                }
+            }
+        }
+    }
+    else if (ErrorCode == WSASERVICE_NOT_FOUND)
+    {
+        /* Normalize the error code */
+        ErrorCode = WSAHOST_NOT_FOUND;
+    }
+
+    /* Finish the lookup if one was in progress */
+    if (LookupHandle) WSALookupServiceEnd(LookupHandle);
+
+    /* Return the error code */
+    return ErrorCode;
+}
+
+static
+INT
+WINAPI
+GetServiceNameForPort(IN LPWSTR pServiceBuffer,
+                      IN DWORD ServiceBufferSize,
+                      IN WORD Port,
+                      IN DWORD Flags)
+{
+    return ERROR_SUCCESS;
+}
+
+static
+INT
+WINAPI
+LookupAddressForName(IN LPCSTR NodeName,
+                     IN INT SocketType,
+                     IN INT Protocol,
+                     IN WORD Port,
+                     IN BOOL bAI_CANONNAME,
+                     OUT PADDRINFOW *pptResult)
+{
+    INT iError = 0;
+    INT AliasCount = 0;
+    CHAR szFQDN1[NI_MAXHOST] = "";
+    CHAR szFQDN2[NI_MAXHOST] = "";
+    PCHAR Name = szFQDN1;
+    PCHAR Alias = szFQDN2;
+    PCHAR Scratch = NULL;
+
+    /* Make a copy of the name */
+    strcpy(Name, NodeName);
+    
+    /* Loop */
+    while (TRUE)
+    {
+        /* Do a DNS Query for the name */
+        iError = QueryDNS(NodeName,
+                          SocketType,
+                          Protocol,
+                          Port,
+                          Alias,
+                          pptResult);
+        if (iError) break;
+
+        /* Exit if we have a result */
+        if (*pptResult) break;
+
+        /* Don't loop continously if this is a DNS misconfiguration */
+        if ((!strlen(Alias)) || (!strcmp(Name, Alias)) || (++AliasCount == 16))
+        {
+            /* Exit the loop with a failure */
+            iError = EAI_FAIL;
+            break;
+        }
+
+        /* Restart loopup if we got a CNAME */
+        Swap(Name, Alias, Scratch);
+    }
+
+    /* Check if we suceeded and the canonical name is requested */
+    if (!iError && bAI_CANONNAME)
+    {
+        /* Allocate memory for a copy */
+        (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 0, 512);
+        
+        /* Check if we had enough memory */
+        if (!(*pptResult)->ai_canonname)
+        {
+            /* Set failure code */
+            iError = EAI_MEMORY;
+        }
+        else
+        {
+            /* Convert the alias to UNICODE */
+            MultiByteToWideChar(CP_ACP, 
+                                0, 
+                                Alias, 
+                                -1, 
+                                (*pptResult)->ai_canonname, 
+                                256);
+        }
+    }
+
+    /* Return to caller */
+    return iError;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+GetAddrInfoW(IN PCWSTR pszNodeName,
+             IN PCWSTR pszServiceName,
+             IN const ADDRINFOW *ptHints,
+             OUT PADDRINFOW *pptResult)
+{
+    INT iError = 0;
+    INT iFlags = 0;
+    INT iFamily = PF_UNSPEC;
+    INT iSocketType = 0;
+    INT iProtocol = 0;
+    WORD wPort = 0;
+    DWORD dwAddress = 0;
+    PSERVENT ptService = NULL;
+    PCHAR pc = NULL;
+    BOOL bClone = FALSE;
+    WORD wTcpPort = 0;
+    WORD wUdpPort = 0;
+    WCHAR CanonicalName[0x42];
+    CHAR AnsiServiceName[256];
+    CHAR AnsiNodeName[256];
+    DPRINT("GetAddrInfoW: %S, %S, %p, %p\n", pszNodeName, pszServiceName, ptHints, pptResult);
+
+    /* Assume error */
+    *pptResult  = NULL;
+
+    /* We must have at least one name to work with */
+    if (!(pszNodeName) && !(pszServiceName))
+    {
+        /* Fail */
+        SetLastError(EAI_NONAME);
+        return EAI_NONAME;
+    }
+
+    /* Check if we got hints */
+    if (ptHints)
+    {
+        /* Make sure these are empty */
+        if ((ptHints->ai_addrlen) ||
+            (ptHints->ai_canonname) ||
+            (ptHints->ai_addr) ||
+            (ptHints->ai_next))
+        {
+            /* Fail if they aren't */
+            SetLastError(EAI_FAIL);
+            return EAI_FAIL;
+        }
+        
+        /* Save the flags and validate them */
+        iFlags = ptHints->ai_flags;
+        if ((iFlags & AI_CANONNAME) && !pszNodeName)
+        {
+            return EAI_BADFLAGS;
+        }
+
+        /* Save family and validate it */
+        iFamily = ptHints->ai_family;
+        if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
+        {
+            return EAI_FAMILY;
+        }
+
+        /* Save socket type and validate it */
+        iSocketType = ptHints->ai_socktype;
+        if ((iSocketType != 0) &&
+            (iSocketType != SOCK_STREAM) &&
+            (iSocketType != SOCK_DGRAM) &&
+            (iSocketType != SOCK_RAW))
+        {
+            return EAI_SOCKTYPE;
+        }
+
+        /* Save the protocol */
+        iProtocol = ptHints->ai_protocol;
+    }
+
+    /* Check if we have a service name */
+    if (pszServiceName)
+    {
+        /* We need to convert it to ANSI */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            pszServiceName, 
+                            -1, 
+                            AnsiServiceName, 
+                            256,
+                            NULL,
+                            0);
+
+        /* Get the port */
+        wPort = (WORD)strtoul(AnsiServiceName, &pc, 10);
+
+        /* Check if the port string is numeric */
+        if (*pc == '\0')
+        {
+            /* Get the port directly */
+            wPort = wTcpPort = wUdpPort = htons(wPort);
+
+            /* Check if this is both TCP and UDP */
+            if (iSocketType == 0)
+            {
+                /* Set it to TCP for now, but remember to clone */
+                bClone = TRUE;
+                iSocketType = SOCK_STREAM;
+            }
+        }
+        else
+        {
+            /* The port name was a string. Check if this is a UDP socket */
+            if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
+            {
+                /* It's UDP, do a getservbyname */
+                ptService = getservbyname(AnsiServiceName, "udp");
+
+                /* If we got a servent, return the port from it */
+                if (ptService) wPort = wUdpPort = ptService->s_port;
+            }
+
+            /* Check if this is a TCP socket */
+            if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
+            {
+                /* It's TCP, do a getserbyname */
+                ptService = getservbyname(AnsiServiceName, "tcp");
+
+                /* Return the port from the servent */
+                if (ptService) wPort = wTcpPort = ptService->s_port;
+            }
+            
+            /* If we got 0, then fail */
+            if (wPort == 0)
+            {
+                return iSocketType ? EAI_SERVICE : EAI_NONAME;
+            }
+
+            /* Check if this was for both */
+            if (iSocketType == 0)
+            {
+                /* Do the TCP case right now */
+                iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
+                bClone = (wTcpPort && wUdpPort); 
+            }
+        }
+    }
+
+    /* Check if no node was given or if this is is a valid IPv4 address */
+    if ((!pszNodeName) || (ParseV4Address(pszNodeName, &dwAddress)))
+    {
+        /* Check if we don't have a node name */
+        if (!pszNodeName)
+        {
+            /* Make one up based on the flags */
+            dwAddress = htonl((iFlags & AI_PASSIVE) ?
+                              INADDR_ANY : INADDR_LOOPBACK);
+        }
+        
+        /* Create the Addr Info */
+        *pptResult = NewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
+
+        /* If we didn't get one back, assume out of memory */
+        if (!(*pptResult)) iError = EAI_MEMORY;
+        
+        /* Check if we have success and a nodename */
+        if (!iError && pszNodeName)
+        {
+            /* Set AI_NUMERICHOST since this is a numeric string */
+            (*pptResult)->ai_flags |= AI_NUMERICHOST;
+            
+            /* Check if the canonical name was requestd */
+            if (iFlags & AI_CANONNAME)
+            {
+                /* Get the canonical name */
+                GetNameInfoW((*pptResult)->ai_addr,
+                             (socklen_t)(*pptResult)->ai_addrlen,
+                             CanonicalName,
+                             0x41,
+                             NULL,
+                             0,
+                             2);
+
+                /* Allocate memory for a copy */
+                (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap,
+                                                       0,
+                                                       wcslen(CanonicalName));
+                
+                if (!(*pptResult)->ai_canonname)
+                {
+                    /* No memory for the copy */
+                    iError = EAI_MEMORY;
+                }
+                else
+                {
+                    /* Duplicate the string */
+                    RtlMoveMemory((*pptResult)->ai_canonname,
+                                  CanonicalName,
+                                  wcslen(CanonicalName));
+                }
+            }
+        }
+    }
+    else if (iFlags & AI_NUMERICHOST)
+    {
+        /* No name for this request (we have a non-numeric name) */
+        iError = EAI_NONAME;
+    }
+    else
+    {
+        /* We need to convert it to ANSI */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            pszNodeName, 
+                            -1, 
+                            AnsiNodeName, 
+                            256,
+                            NULL,
+                            0);
+
+        /* Non-numeric name, do DNS lookup */
+        iError = LookupAddressForName(AnsiNodeName,
+                                      iSocketType,
+                                      iProtocol,
+                                      wPort,
+                                      (iFlags & AI_CANONNAME),
+                                      pptResult);
+    }
+
+    /* If all was good and the caller requested UDP and TCP */
+    if (!iError && bClone)
+    {
+        /* Process UDP now, we already did TCP */
+        iError = CloneAddrInfo(wUdpPort, *pptResult);
+    }
+
+    /* If we've hit an error till here */
+    if (iError)
+    {
+        /* Free the address info and return nothing */
+        FreeAddrInfoW(*pptResult);
+        *pptResult = NULL;        
+    }
+
+    /* Return to caller */
+    return iError;
+}
+
+#undef freeaddrinfo
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+freeaddrinfo(PADDRINFOA AddrInfo)
+{
+    PADDRINFOA NextInfo;
+
+    /* Loop the chain of structures */
+    for (NextInfo = AddrInfo; NextInfo; NextInfo = AddrInfo)
+    {
+        /* Check if there is a canonical name */
+        if (NextInfo->ai_canonname)
+        {
+            /* Free it */
+            HeapFree(WsSockHeap, 0, NextInfo->ai_canonname);
+        }
+        
+        /* Check if there is an address */
+        if (NextInfo->ai_addr)
+        {
+            /* Free it */
+            HeapFree(WsSockHeap, 0, NextInfo->ai_addr);
+        }
+
+        /* Move to the next entry */
+        AddrInfo = NextInfo->ai_next;
+
+        /* Free this entry */
+        HeapFree(WsSockHeap, 0, NextInfo);
+    }
+}
+
+#undef getaddrinfo
+/*
+ * @implemented
+ */
+INT
+WINAPI
+getaddrinfo(const char FAR *nodename,
+            const char FAR *servname,
+            const struct addrinfo FAR *hints,
+            struct addrinfo FAR * FAR *res)
+{
+    INT ErrorCode;
+    LPWSTR UnicodeNodeName;
+    LPWSTR UnicodeServName = NULL; 
+    DPRINT("getaddrinfo: %s, %s, %p, %p\n", nodename, servname, hints, res);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
+
+    /* Assume NULL */
+    *res = NULL;
+
+    /* Convert the node name */
+    UnicodeNodeName = UnicodeDupFromAnsi((LPSTR)nodename);
+    if (!UnicodeNodeName)
+    {
+        /* Prepare to fail */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Convert the servname too, if we have one */
+    if (servname)
+    {
+        UnicodeServName = UnicodeDupFromAnsi((LPSTR)servname);
+        if (!UnicodeServName)
+        {
+            /* Prepare to fail */
+            ErrorCode = GetLastError();
+            goto Quickie;
+        }
+    }
+  
+    /* Now call the unicode function */
+    ErrorCode = GetAddrInfoW(UnicodeNodeName,
+                             UnicodeServName,
+                             (PADDRINFOW)hints,
+                             (PADDRINFOW*)res);
+
+    /* Convert it to ANSI if we suceeded */
+    if (ErrorCode == ERROR_SUCCESS) ConvertAddrinfoFromUnicodeToAnsi((PADDRINFOW)*res);
+
+Quickie:
+    /* Check if we have a unicode node name and serv name */
+    if (UnicodeNodeName) HeapFree(WsSockHeap, 0, UnicodeNodeName);
+    if (UnicodeServName) HeapFree(WsSockHeap, 0, UnicodeServName);
+
+    /* Check if we are in error */
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Free the structure and return nothing */
+        freeaddrinfo(*res);
+        *res = NULL;
+    }
+
+    /* Set the last error and return */
+    SetLastError(ErrorCode);
+    return ErrorCode;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+GetNameInfoW(IN CONST SOCKADDR *pSockaddr,
+             IN socklen_t SockaddrLength,
+             OUT PWCHAR pNodeBuffer,
+             IN DWORD NodeBufferSize,
+             OUT PWCHAR pServiceBuffer,
+             IN DWORD ServiceBufferSize,
+             IN INT Flags)
+{
+    DWORD AddressLength, AddrSize;
+    PVOID Addr;
+    SOCKADDR_IN Address;
+    INT ErrorCode = ERROR_SUCCESS;
+
+    /* Check for valid socket */
+    if (!pSockaddr) return EAI_FAIL;
+    
+    /* Check which family this is */
+    if (pSockaddr->sa_family == AF_INET)
+    {
+        /* IPv4 */
+        AddressLength = sizeof(SOCKADDR_IN);
+        Addr = &((PSOCKADDR_IN)pSockaddr)->sin_addr;
+        AddrSize = sizeof(IN_ADDR);
+    }
+    else if (pSockaddr->sa_family == AF_INET6)
+    {
+        /* IPv6 */
+        AddressLength = sizeof(SOCKADDR_IN6);
+        Addr = &((PSOCKADDR_IN6)pSockaddr)->sin6_addr;
+        AddrSize = sizeof(IN6_ADDR);
+    }
+    else
+    {
+        /* Unsupported family */
+        return EAI_FAMILY;
+    } 
+
+    /* Check for valid socket adress length */
+    if ((DWORD)SockaddrLength < AddressLength) return EAI_FAIL;
+    
+    /* Check if we have a node name */
+    if (pNodeBuffer)
+    {    
+        /* Check if only the numeric host is wanted */
+        if (!(Flags & NI_NUMERICHOST))
+        {
+            /* Do the lookup by addr */
+            ErrorCode = LookupNodeByAddr(pNodeBuffer,
+                                         NodeBufferSize,
+                                         Flags & NI_NOFQDN,
+                                         Addr,
+                                         AddrSize,
+                                         pSockaddr->sa_family);
+            /* Check if we failed */
+            if (ErrorCode != ERROR_SUCCESS)
+            {
+                /* Fail if the caller REALLY wants the NAME itself? */
+                if (Flags & NI_NAMEREQD) goto quickie;
+            }
+            else
+            {
+                /* We suceeded, no need to get the numeric address */
+                goto SkipNumeric;
+            }
+        }
+
+        /* Copy the address */
+        RtlMoveMemory(&Address, pSockaddr, AddressLength);
+
+        /* Get the numeric address */
+        Address.sin_port = 0;
+        ErrorCode = WSAAddressToStringW((LPSOCKADDR)&Address,
+                                        AddressLength,
+                                        NULL,
+                                        pNodeBuffer,
+                                        &NodeBufferSize);
+        if (ErrorCode == SOCKET_ERROR)
+        {
+            /* Get the error code and exit with it */
+            ErrorCode = GetLastError();
+            goto quickie;
+        }
+    }
+
+SkipNumeric:
+    /* Check if we got a service name */
+    if (pServiceBuffer)
+    {
+        /* Handle this request */
+        ErrorCode = GetServiceNameForPort(pServiceBuffer,
+                                          ServiceBufferSize,
+                                          ((PSOCKADDR_IN)pSockaddr)->sin_port,
+                                          Flags);
+    }
+
+    /* Set the error and return it (or success) */
+quickie:
+    SetLastError(ErrorCode);
+    return ErrorCode;
+}
+
+#undef getnameinfo
+/*
+ * @implemented
+ */
+INT
+WINAPI
+getnameinfo(const struct sockaddr FAR *sa,
+            socklen_t salen,
+            char FAR *host,
+            DWORD hostlen,
+            char FAR *serv,
+            DWORD servlen,
+            INT flags)
+{
+    INT ErrorCode;
+    WCHAR Buffer[256];
+    WCHAR ServiceBuffer[17];
+    DWORD HostLength = 0, ServLength = 0;
+    PWCHAR ServiceString = NULL, HostString = NULL;
+    DPRINT("getaddrinfo: %p, %p, %p, %lx\n", host, serv, sa, salen);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
+
+    /* Check if we have a host pointer */
+    if (host)
+    {
+        /* Setup the data for it */
+        HostString = Buffer;
+        HostLength = sizeof(Buffer) / sizeof(WCHAR);
+    }
+
+    /* Check if we have a service pointer */
+    if (serv)
+    {
+        /* Setup the data for it */
+        ServiceString = ServiceBuffer;
+        ServLength = sizeof(ServiceBuffer) - 1;
+    }
+  
+    /* Now call the unicode function */
+    ErrorCode = GetNameInfoW(sa,
+                             salen,
+                             HostString,
+                             HostLength,
+                             ServiceString,
+                             ServLength,
+                             flags);
+
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Check if we had a host pointer */
+        if (HostString)
+        {
+            /* Convert it back to ANSI */
+            ErrorCode = WideCharToMultiByte(CP_ACP,
+                                            0,
+                                            HostString,
+                                            -1,
+                                            host,
+                                            hostlen,
+                                            NULL,
+                                            NULL);
+            if (!ErrorCode) goto Quickie;
+        }
+
+        /* Check if we have a service pointer */
+        if (ServiceString)
+        {
+            /* Convert it back to ANSI */
+            ErrorCode = WideCharToMultiByte(CP_ACP,
+                                            0,
+                                            ServiceString,
+                                            -1,
+                                            serv,
+                                            servlen,
+                                            NULL,
+                                            NULL);
+            if (!ErrorCode) goto Quickie;
+        }
+
+        /* Return success */
+        return ERROR_SUCCESS;
+    }
+
+    /* Set the last error and return */
+Quickie:
+    SetLastError(ErrorCode);
+    return ErrorCode;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/async.c b/reactos/dll/win32/ws2_32_new/src/async.c
new file mode 100644 (file)
index 0000000..8401c07
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        async.c
+ * PURPOSE:     Async Block Object and Async Thread Management
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+BOOLEAN WsAsyncThreadInitialized;
+LONG WsAsyncTaskHandle;
+PLIST_ENTRY WsAsyncQueue;
+CRITICAL_SECTION WsAsyncCritSect;
+HANDLE WsAsyncEvent;
+HANDLE WsAsyncCurrentTaskHandle;
+HANDLE WsAsyncCancelledTaskHandle;
+HINSTANCE WsAsyncDllHandle;
+
+#define WsAsyncLock()   EnterCriticalSection(&WsAsyncCritSect);
+#define WsAsyncUnlock() LeaveCriticalSection(&WsAsyncCritSect);
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WSAAPI
+WsAsyncGlobalInitialize(VOID)
+{
+    /* Initialize the async lock */
+    InitializeCriticalSection(&WsAsyncCritSect);
+}
+
+VOID
+WSAAPI
+WsAsyncGlobalTerminate(VOID)
+{
+    /* Destroy the async lock */
+    DeleteCriticalSection(&WsAsyncCritSect);
+}
+
+
+SIZE_T
+WSAAPI
+BytesInHostent(PHOSTENT Hostent)
+{
+    SIZE_T Bytes;
+    INT i;
+
+    /* Start with the static stuff */
+    Bytes = sizeof(HOSTENT) + strlen(Hostent->h_name) + sizeof(CHAR);
+
+    /* Add 2 pointers for the list-terminators */
+    Bytes += 2 * sizeof(ULONG_PTR);
+
+    /* Now loop for the alises */
+    for (i = 0; Hostent->h_aliases[i]; i++)
+    {
+        /* Add the alias size, plus the space its pointer takes */
+        Bytes += strlen(Hostent->h_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR);
+    }
+
+    /* Now loop for the hostnames  */
+    for (i = 0; Hostent->h_addr_list[i]; i++)
+    {
+        /* Add the alias size, plus the space its pointer takes */
+        Bytes += Hostent->h_length + sizeof(ULONG_PTR);
+    }
+
+    /* Align to 8 bytes */
+    return (Bytes + 7) & ~7;
+}
+
+SIZE_T
+WSAAPI
+BytesInServent(PSERVENT Servent)
+{
+    SIZE_T Bytes;
+    INT i;
+
+    /* Start with the static stuff */
+    Bytes = sizeof(SERVENT) +
+            strlen(Servent->s_name) + sizeof(CHAR) +
+            strlen(Servent->s_proto) + sizeof(CHAR);
+
+    /* Add 1 pointers for the list terminator */
+    Bytes += sizeof(ULONG_PTR);
+
+    /* Now loop for the alises */
+    for (i = 0; Servent->s_aliases[i]; i++)
+    {
+        /* Add the alias size, plus the space its pointer takes */
+        Bytes += strlen(Servent->s_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR);
+    }
+
+    /* return */
+    return Bytes;
+}
+
+SIZE_T
+WSAAPI
+BytesInProtoent(PPROTOENT Protoent)
+{
+    SIZE_T Bytes;
+    INT i;
+
+    /* Start with the static stuff */
+    Bytes = sizeof(SERVENT) + strlen(Protoent->p_name) + sizeof(CHAR);
+
+    /* Add 1 pointers for the list terminator */
+    Bytes += sizeof(ULONG_PTR);
+
+    /* Now loop for the alises */
+    for (i = 0; Protoent->p_aliases[i]; i++)
+    {
+        /* Add the alias size, plus the space its pointer takes */
+        Bytes += strlen(Protoent->p_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR);
+    }
+
+    /* return */
+    return Bytes;
+}
+
+SIZE_T
+WSAAPI
+CopyHostentToBuffer(IN PCHAR Buffer,
+                    IN INT BufferLength,
+                    IN PHOSTENT Hostent)
+{
+    SIZE_T BufferSize, CurrentSize, NameSize;
+    PCHAR p = Buffer;
+    DWORD Aliases = 0, Names = 0;
+    DWORD i;
+    PHOSTENT ReturnedHostent = (PHOSTENT)Buffer;
+
+    /* Determine the buffer size required */
+    BufferSize = BytesInHostent(Hostent);
+
+    /* Check which size to use */
+    if ((DWORD)BufferLength > BufferSize)
+    {
+        /* Zero the buffer */
+        RtlZeroMemory(Buffer, BufferSize);
+    }
+    else
+    {
+        /* Zero the buffer */
+        RtlZeroMemory(Buffer, BufferLength);
+    }
+
+    /* Start with the raw Hostent */
+    CurrentSize = sizeof(HOSTENT);
+
+    /* Return the size needed now */
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Copy the Hostent and initialize it */
+    CopyMemory(p, Hostent, sizeof(HOSTENT));
+    p = Buffer + CurrentSize;
+    ReturnedHostent->h_name = NULL;
+    ReturnedHostent->h_aliases = NULL;
+    ReturnedHostent->h_addr_list = NULL;
+
+    /* Find out how many aliases there are */
+    while (Hostent->h_aliases[Aliases])
+    {
+        /* Increase the alias count */
+        Aliases++;
+    }
+
+    /* Add the aliases to the size, and validate it */
+    CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR);
+    if (CurrentSize > (DWORD)BufferLength)
+    {
+        /* Clear the aliases and return */
+        Hostent->h_aliases = NULL;
+        return BufferSize;
+    }
+
+    /* Write the aliases, update the pointer */
+    ReturnedHostent->h_aliases = (PCHAR*)p;
+    p = Buffer + CurrentSize;
+
+    /* Find out how many names there are */
+    while (Hostent->h_addr_list[Names])
+    {
+        /* Increase the alias count */
+        Names++;
+    }
+
+    /* Add the names to the size, and validate it */
+    CurrentSize += (Names + 1) * sizeof(ULONG_PTR);
+    if (CurrentSize > (DWORD)BufferLength)
+    {
+        /* Clear the aliases and return */
+        Hostent->h_addr_list = NULL;
+        return BufferSize;
+    }
+
+    /* Write the names, update the pointer */
+    ReturnedHostent->h_addr_list = (PCHAR*)p;
+    p = Buffer + CurrentSize;
+
+    /* Now add the names */
+    for (i = 0; i < Names; i++)
+    {
+        /* Update size and validate */
+        CurrentSize += Hostent->h_length;
+        if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+        /* Write pointer and copy */
+        ReturnedHostent->h_addr_list[i] = p;
+        CopyMemory(p, Hostent->h_addr_list[i], Hostent->h_length);
+
+        /* Update pointer */
+        p = Buffer + CurrentSize;
+    }
+
+    /* Finalize the list */
+    ReturnedHostent->h_addr_list[i] = NULL;
+
+    /* Add the service name to the size, and validate it */
+    NameSize = strlen(Hostent->h_name) + sizeof(CHAR);
+    CurrentSize += NameSize;
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Write the service name and update the pointer */
+    ReturnedHostent->h_name = p;
+    CopyMemory(p, Hostent->h_name, NameSize);
+    p = Buffer + CurrentSize;
+
+    /* Now add the aliases */
+    for (i = 0; i < Aliases; i++)
+    {
+        /* Update size and validate */
+        NameSize = strlen(Hostent->h_aliases[i]) + sizeof(CHAR);
+        CurrentSize += NameSize;
+        if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+        /* Write pointer and copy */
+        ReturnedHostent->h_aliases[i] = p;
+        CopyMemory(p, Hostent->h_aliases[i], NameSize);
+
+        /* Update pointer */
+        p = Buffer + CurrentSize;
+    }
+
+    /* Finalize the list and return */
+    ReturnedHostent->h_aliases[i] = NULL;
+    return BufferSize;
+}
+
+SIZE_T
+WSAAPI
+CopyServentToBuffer(IN PCHAR Buffer,
+                    IN INT BufferLength,
+                    IN PSERVENT Servent)
+{
+    SIZE_T BufferSize, CurrentSize, NameSize;
+    PCHAR p = Buffer;
+    DWORD Aliases = 0;
+    DWORD i;
+    PSERVENT ReturnedServent = (PSERVENT)Buffer;
+
+    /* Determine the buffer size required */
+    BufferSize = BytesInServent(Servent);
+
+    /* Check which size to use */
+    if ((DWORD)BufferLength > BufferSize)
+    {
+        /* Zero the buffer */
+        ZeroMemory(Buffer, BufferSize);
+    }
+    else
+    {
+        /* Zero the buffer */
+        ZeroMemory(Buffer, BufferLength);
+    }
+
+    /* Start with the raw servent */
+    CurrentSize = sizeof(SERVENT);
+
+    /* Return the size needed now */
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Copy the servent and initialize it */
+    CopyMemory(p, Servent, sizeof(SERVENT));
+    p = Buffer + CurrentSize;
+    ReturnedServent->s_name = NULL;
+    ReturnedServent->s_aliases = NULL;
+    ReturnedServent->s_proto = NULL;
+
+    /* Find out how many aliases there are */
+    while (Servent->s_aliases[Aliases])
+    {
+        /* Increase the alias count */
+        Aliases++;
+    }
+
+    /* Add the aliases to the size, and validate it */
+    CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR);
+    if (CurrentSize > (DWORD)BufferLength)
+    {
+        /* Clear the aliases and return */
+        Servent->s_aliases = NULL;
+        return BufferSize;
+    }
+
+    /* Write the aliases, update the pointer */
+    ReturnedServent->s_aliases = (PCHAR*)p;
+    p = Buffer + CurrentSize;
+
+    /* Add the service name to the size, and validate it */
+    NameSize = strlen(Servent->s_name) + sizeof(CHAR);
+    CurrentSize += NameSize;
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Write the service name and update the pointer */
+    ReturnedServent->s_name = p;
+    CopyMemory(p, Servent->s_name, NameSize);
+    p = Buffer + CurrentSize;
+
+    /* Now add the aliases */
+    for (i = 0; i < Aliases; i++)
+    {
+        /* Update size and validate */
+        NameSize = strlen(Servent->s_aliases[i]) + sizeof(CHAR);
+        CurrentSize += NameSize;
+        if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+        /* Write pointer and copy */
+        ReturnedServent->s_aliases[i] = p;
+        CopyMemory(p, Servent->s_aliases[i], NameSize);
+
+        /* Update pointer */
+        p = Buffer + CurrentSize;
+    }
+
+    /* Finalize the list and return */
+    ReturnedServent->s_aliases[i] = NULL;
+    return BufferSize;
+}
+
+SIZE_T
+WSAAPI
+CopyProtoentToBuffer(IN PCHAR Buffer,
+                     IN INT BufferLength,
+                     IN PPROTOENT Protoent)
+{
+    SIZE_T BufferSize, CurrentSize, NameSize;
+    PCHAR p = Buffer;
+    DWORD Aliases = 0;
+    DWORD i;
+    PPROTOENT ReturnedProtoent = (PPROTOENT)Buffer;
+
+    /* Determine the buffer size required */
+    BufferSize = BytesInProtoent(Protoent);
+
+    /* Check which size to use */
+    if ((DWORD)BufferLength > BufferSize)
+    {
+        /* Zero the buffer */
+        ZeroMemory(Buffer, BufferSize);
+    }
+    else
+    {
+        /* Zero the buffer */
+        ZeroMemory(Buffer, BufferLength);
+    }
+
+    /* Start with the raw servent */
+    CurrentSize = sizeof(PROTOENT);
+
+    /* Return the size needed now */
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Copy the servent and initialize it */
+    CopyMemory(p, Protoent, sizeof(PROTOENT));
+    p = Buffer + CurrentSize;
+    ReturnedProtoent->p_name = NULL;
+    ReturnedProtoent->p_aliases = NULL;
+
+    /* Find out how many aliases there are */
+    while (Protoent->p_aliases[Aliases])
+    {
+        /* Increase the alias count */
+        Aliases++;
+    }
+
+    /* Add the aliases to the size, and validate it */
+    CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR);
+    if (CurrentSize > (DWORD)BufferLength)
+    {
+        /* Clear the aliases and return */
+        Protoent->p_aliases = NULL;
+        return BufferSize;
+    }
+
+    /* Write the aliases, update the pointer */
+    ReturnedProtoent->p_aliases = (PCHAR*)p;
+    p = Buffer + CurrentSize;
+
+    /* Add the service name to the size, and validate it */
+    NameSize = strlen(Protoent->p_name) + sizeof(CHAR);
+    CurrentSize += NameSize;
+    if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+    /* Write the service name and update the pointer */
+    ReturnedProtoent->p_name = p;
+    CopyMemory(p, Protoent->p_name, NameSize);
+    p = Buffer + CurrentSize;
+
+    /* Now add the aliases */
+    for (i = 0; i < Aliases; i++)
+    {
+        /* Update size and validate */
+        NameSize = strlen(Protoent->p_aliases[i]) + sizeof(CHAR);
+        CurrentSize += NameSize;
+        if (CurrentSize > (DWORD)BufferLength) return BufferSize;
+
+        /* Write pointer and copy */
+        ReturnedProtoent->p_aliases[i] = p;
+        CopyMemory(p, Protoent->p_aliases[i], NameSize);
+
+        /* Update pointer */
+        p = Buffer + CurrentSize;
+    }
+
+    /* Finalize the list and return */
+    ReturnedProtoent->p_aliases[i] = NULL;
+    return BufferSize;
+}
+
+PWSASYNCBLOCK
+WSAAPI
+WsAsyncAllocateBlock(IN SIZE_T ExtraLength)
+{
+    PWSASYNCBLOCK AsyncBlock;
+
+    /* Add the size of the block */
+    ExtraLength += sizeof(WSASYNCBLOCK);
+
+    /* Allocate it */
+    AsyncBlock = HeapAlloc(WsSockHeap, 0, ExtraLength);
+
+    /* Get a handle to it */
+    AsyncBlock->TaskHandle = UlongToPtr(InterlockedIncrement(&WsAsyncTaskHandle));
+
+    /* Return it */
+    return AsyncBlock;
+}
+
+BOOL
+WINAPI
+WsAsyncThreadBlockingHook(VOID)
+{
+    /* Check if this task is being cancelled */
+    if (WsAsyncCurrentTaskHandle == WsAsyncCancelledTaskHandle)
+    {
+        /* Cancel the blocking call so we can get back */
+        WSACancelBlockingCall();
+    }
+
+    /* Return to system */
+    return FALSE;
+}
+
+VOID
+WSAAPI
+WsAsyncFreeBlock(IN PWSASYNCBLOCK AsyncBlock)
+{
+    /* Free it */
+    HeapFree(WsSockHeap, 0, AsyncBlock);
+}
+
+VOID
+WSAAPI
+WsAsyncGetServ(IN HANDLE TaskHandle,
+               IN DWORD Operation,
+               IN HWND hWnd,
+               IN UINT wMsg,
+               IN CHAR FAR *ByWhat,
+               IN CHAR FAR *Protocol,
+               IN CHAR FAR *Buffer,
+               IN INT BufferLength)
+{
+    PSERVENT Servent;
+    SIZE_T BufferSize = 0;
+    LPARAM lParam;
+    INT ErrorCode = 0;
+
+    /* Check the operaiton */
+    if (Operation == WsAsyncGetServByName)
+    {
+        /* Call the API */
+        Servent = getservbyname(ByWhat, Protocol);
+    }
+    else
+    {
+        /* Call the API */
+        Servent = getservbyport(PtrToUlong(ByWhat), Protocol);
+    }
+
+    /* Make sure we got one */
+    if (!Servent) ErrorCode = GetLastError();
+
+    /* Acquire the lock */
+    WsAsyncLock();
+
+    /* Check if this task got cancelled */
+    if (TaskHandle == WsAsyncCancelledTaskHandle)
+    {
+        /* Return */
+        WsAsyncUnlock();
+        return;
+    }
+
+    /* If we got a Servent back, copy it */
+    if (Servent)
+    {
+        /* Copy it into the buffer */
+        BufferSize = CopyServentToBuffer(Buffer, BufferLength, Servent);
+
+        /* Check if we had enough space */
+        if (BufferSize > (DWORD)BufferLength)
+        {
+            /* Not enough */
+            ErrorCode = WSAENOBUFS;
+        }
+        else
+        {
+            /* Perfect */
+            ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Not processing anyomre */
+    WsAsyncCurrentTaskHandle = NULL;
+
+    /* Release the lock */
+    WsAsyncUnlock();
+
+    /* Make the messed-up lParam reply */
+    lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode);
+
+    /* Sent it through the Upcall API */
+    WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam);
+}
+
+VOID
+WSAAPI
+WsAsyncGetProto(IN HANDLE TaskHandle,
+                IN DWORD Operation,
+                IN HWND hWnd,
+                IN UINT wMsg,
+                IN CHAR FAR *ByWhat,
+                IN CHAR FAR *Buffer,
+                IN INT BufferLength)
+{
+    PPROTOENT Protoent;
+    SIZE_T BufferSize = 0;
+    LPARAM lParam;
+    INT ErrorCode = 0;
+
+    /* Check the operaiton */
+    if (Operation == WsAsyncGetProtoByName)
+    {
+        /* Call the API */
+        Protoent = getprotobyname(ByWhat);
+    }
+    else
+    {
+        /* Call the API */
+        Protoent = getprotobynumber(PtrToUlong(ByWhat));
+    }
+
+    /* Make sure we got one */
+    if (!Protoent) ErrorCode = GetLastError();
+
+    /* Acquire the lock */
+    WsAsyncLock();
+
+    /* Check if this task got cancelled */
+    if (TaskHandle == WsAsyncCancelledTaskHandle)
+    {
+        /* Return */
+        WsAsyncUnlock();
+        return;
+    }
+
+    /* If we got a Servent back, copy it */
+    if (Protoent)
+    {
+        /* Copy it into the buffer */
+        BufferSize = CopyProtoentToBuffer(Buffer, BufferLength, Protoent);
+
+        /* Check if we had enough space */
+        if (BufferSize > (DWORD)BufferLength)
+        {
+            /* Not enough */
+            ErrorCode = WSAENOBUFS;
+        }
+        else
+        {
+            /* Perfect */
+            ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Not processing anyomre */
+    WsAsyncCurrentTaskHandle = NULL;
+
+    /* Release the lock */
+    WsAsyncUnlock();
+
+    /* Make the messed-up lParam reply */
+    lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode);
+
+    /* Sent it through the Upcall API */
+    WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam);
+}
+
+VOID
+WSAAPI
+WsAsyncGetHost(IN HANDLE TaskHandle,
+               IN DWORD Operation,
+               IN HWND hWnd,
+               IN UINT wMsg,
+               IN CHAR FAR *ByWhat,
+               IN INT Length,
+               IN INT Type,
+               IN CHAR FAR *Buffer,
+               IN INT BufferLength)
+{
+    PHOSTENT Hostent;
+    SIZE_T BufferSize = 0;
+    LPARAM lParam;
+    INT ErrorCode = 0;
+
+    /* Check the operaiton */
+    if (Operation == WsAsyncGetHostByAddr)
+    {
+        /* Call the API */
+        Hostent = gethostbyaddr(ByWhat, Length, Type);
+    }
+    else
+    {
+        /* Call the API */
+        Hostent = gethostbyname(ByWhat);
+    }
+
+    /* Make sure we got one */
+    if (!Hostent) ErrorCode = GetLastError();
+
+    /* Acquire the lock */
+    WsAsyncLock();
+
+    /* Check if this task got cancelled */
+    if (TaskHandle == WsAsyncCancelledTaskHandle)
+    {
+        /* Return */
+        WsAsyncUnlock();
+        return;
+    }
+
+    /* If we got a Servent back, copy it */
+    if (Hostent)
+    {
+        /* Copy it into the buffer */
+        BufferSize = CopyHostentToBuffer(Buffer, BufferLength, Hostent);
+
+        /* Check if we had enough space */
+        if (BufferSize > (DWORD)BufferLength)
+        {
+            /* Not enough */
+            ErrorCode = WSAENOBUFS;
+        }
+        else
+        {
+            /* Perfect */
+            ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Not processing anyomre */
+    WsAsyncCurrentTaskHandle = NULL;
+
+    /* Release the lock */
+    WsAsyncUnlock();
+
+    /* Make the messed-up lParam reply */
+    lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode);
+
+    /* Sent it through the Upcall API */
+    WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam);
+}
+
+DWORD
+WINAPI
+WsAsyncThread(IN PWSASYNCCONTEXT Context)
+{
+    PWSASYNCBLOCK AsyncBlock;
+    PLIST_ENTRY Entry;
+    FARPROC OldHook;
+    HANDLE AsyncEvent = Context->AsyncEvent;
+    PLIST_ENTRY ListHead = &Context->AsyncQueue;
+
+    /* Set the blocking hook */
+    OldHook = WSASetBlockingHook((FARPROC)WsAsyncThreadBlockingHook);
+
+    /* Loop */
+    while (TRUE)
+    {
+        /* Wait for the event */
+        WaitForSingleObject(AsyncEvent, INFINITE);
+
+        /* Get the lock */
+        WsAsyncLock();
+
+        /* Process the queue */
+        while (ListHead->Flink != ListHead)
+        {
+            /* Remove this entry and get the async block */
+            Entry = RemoveHeadList(ListHead);
+            AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue);
+
+            /* Save the current task handle */
+            WsAsyncCurrentTaskHandle = AsyncBlock->TaskHandle;
+
+            /* Release the lock */
+            WsAsyncUnlock();
+
+            /* Check which operation to do */
+            switch (AsyncBlock->Operation)
+            {
+                /* Get Host by Y */
+                case WsAsyncGetHostByAddr: case WsAsyncGetHostByName:
+
+                    /* Call the handler */
+                    WsAsyncGetHost(AsyncBlock->TaskHandle,
+                                   AsyncBlock->Operation,
+                                   AsyncBlock->GetHost.hWnd,
+                                   AsyncBlock->GetHost.wMsg,
+                                   AsyncBlock->GetHost.ByWhat,
+                                   AsyncBlock->GetHost.Length,
+                                   AsyncBlock->GetHost.Type,
+                                   AsyncBlock->GetHost.Buffer,
+                                   AsyncBlock->GetHost.BufferLength);
+                    break;
+
+                /* Get Proto by Y */
+                case WsAsyncGetProtoByNumber: case WsAsyncGetProtoByName:
+
+                    /* Call the handler */
+                    WsAsyncGetProto(AsyncBlock->TaskHandle,
+                                    AsyncBlock->Operation,
+                                    AsyncBlock->GetProto.hWnd,
+                                    AsyncBlock->GetProto.wMsg,
+                                    AsyncBlock->GetHost.ByWhat,
+                                    AsyncBlock->GetProto.Buffer,
+                                    AsyncBlock->GetProto.BufferLength);
+                    break;
+
+                /* Get Serv by Y */
+                case WsAsyncGetServByPort: case WsAsyncGetServByName:
+
+                    /* Call the handler */
+                    WsAsyncGetServ(AsyncBlock->TaskHandle,
+                                   AsyncBlock->Operation,
+                                   AsyncBlock->GetServ.hWnd,
+                                   AsyncBlock->GetServ.wMsg,
+                                   AsyncBlock->GetServ.ByWhat,
+                                   AsyncBlock->GetServ.Protocol,
+                                   AsyncBlock->GetServ.Buffer,
+                                   AsyncBlock->GetServ.BufferLength);
+                    break;
+
+                /* Termination */
+                case WsAsyncTerminate:
+
+                    /* Clean up the extra reference */
+                    WSACleanup();
+
+                    /* Free the context block */
+                    WsAsyncFreeBlock(AsyncBlock);
+
+                    /* Acquire the lock */
+                    WsAsyncLock();
+
+                    /* Loop the queue and flush it */
+                    while (!IsListEmpty(ListHead))
+                    {
+                        Entry = RemoveHeadList(ListHead);
+                        AsyncBlock = CONTAINING_RECORD(Entry,
+                                                       WSASYNCBLOCK,
+                                                       AsyncQueue);
+                        WsAsyncFreeBlock(AsyncBlock);
+                    }
+
+                    /* Release lock */
+                    WsAsyncUnlock();
+
+                    /* Close the event, free the Context */
+                    CloseHandle(AsyncEvent);
+                    HeapFree(WsSockHeap, 0, Context);
+
+                    /* Remove the extra DLL reference and kill us */
+                    FreeLibraryAndExitThread(WsAsyncDllHandle, 0);
+
+                default:
+                    break;
+            }
+
+            /* Done processing */
+            WsAsyncCurrentTaskHandle = NULL;
+
+            /* Free this block, get lock and reloop */
+            WsAsyncFreeBlock(AsyncBlock);
+            WsAsyncLock();
+        }
+
+        /* Release the lock */
+        WsAsyncUnlock();
+    }
+}
+
+BOOL
+WSAAPI
+WsAsyncCheckAndInitThread(VOID)
+{
+    HANDLE ThreadHandle;
+    DWORD Tid;
+    PWSASYNCCONTEXT Context = NULL;
+    WSADATA WsaData;
+
+    /* Make sure we're not initialized */
+    if (WsAsyncThreadInitialized) return TRUE;
+
+    /* Acquire the lock */
+    WsAsyncLock();
+
+    /* Make sure we're not initialized */
+    if (!WsAsyncThreadInitialized)
+    {
+        /* Initialize Thread Context */
+        Context = HeapAlloc(WsSockHeap, 0, sizeof(*Context));
+
+        /* Initialize the Queue and event */
+        WsAsyncQueue = &Context->AsyncQueue;
+        InitializeListHead(WsAsyncQueue);
+        Context->AsyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        WsAsyncEvent = Context->AsyncEvent;
+
+        /* Prevent us from ever being killed while running */
+        WSAStartup(MAKEWORD(2,2), &WsaData);
+
+        /* Create the thread */
+        ThreadHandle = CreateThread(NULL,
+                                    0,
+                                    (LPTHREAD_START_ROUTINE)WsAsyncThread,
+                                    Context,
+                                    0,
+                                    &Tid);
+
+        /* Close the handle and set init */
+        CloseHandle(ThreadHandle);
+        WsAsyncThreadInitialized = TRUE;
+    }
+
+    /* Release the lock */
+    WsAsyncUnlock();
+    return WsAsyncThreadInitialized;
+}
+
+VOID
+WSAAPI
+WsAsyncTerminateThread(VOID)
+{
+    PWSASYNCBLOCK AsyncBlock;
+
+    /* Make sure we're initialized */
+    if (!WsAsyncThreadInitialized) return;
+
+    /* Allocate a block */
+    AsyncBlock = WsAsyncAllocateBlock(0);
+
+    /* Initialize it for termination */
+    AsyncBlock->Operation = WsAsyncTerminate;
+
+    /* Queue the request and return */
+    WsAsyncQueueRequest(AsyncBlock);
+    WsAsyncThreadInitialized = FALSE;
+}
+
+VOID
+WSAAPI
+WsAsyncQueueRequest(IN PWSASYNCBLOCK AsyncBlock)
+{
+    /* Get the lock */
+    WsAsyncLock();
+
+    /* Insert it into the queue */
+    InsertTailList(WsAsyncQueue, &AsyncBlock->AsyncQueue);
+
+    /* Wake up the thread */
+    SetEvent(WsAsyncEvent);
+
+    /* Release lock and return */
+    WsAsyncUnlock();
+}
+
+INT
+WSAAPI
+WsAsyncCancelRequest(IN HANDLE TaskHandle)
+{
+    PLIST_ENTRY Entry;
+    PWSASYNCBLOCK AsyncBlock;
+
+    /* Make sure we're initialized */
+    if (!WsAsyncThreadInitialized) return WSAEINVAL;
+
+    /* Acquire the lock */
+    WsAsyncLock();
+
+    /* Check if we're cancelling the current task */
+    if (TaskHandle == WsAsyncCurrentTaskHandle)
+    {
+        /* Mark us as cancelled, the async thread will see this later */
+        WsAsyncCancelledTaskHandle = TaskHandle;
+
+        /* Release lock and return */
+        WsAsyncUnlock();
+        return NO_ERROR;
+    }
+
+    /* Loop the queue */
+    Entry = WsAsyncQueue->Flink;
+    while (Entry != WsAsyncQueue)
+    {
+        /* Get the Async Block */
+        AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue);
+
+        /* Check if this is the one */
+        if (TaskHandle == AsyncBlock->TaskHandle)
+        {
+            /* It is, remove it */
+            RemoveEntryList(Entry);
+
+            /* Release the lock, free the block, and return */
+            WsAsyncUnlock();
+            WsAsyncFreeBlock(AsyncBlock);
+            return NO_ERROR;
+        }
+        
+        /* Move to the next entry */
+        Entry = Entry->Flink;
+    }
+
+    /* Nothing found, fail */
+    WsAsyncUnlock();
+    return WSAEINVAL;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/bhook.c b/reactos/dll/win32/ws2_32_new/src/bhook.c
new file mode 100644 (file)
index 0000000..b6d357a
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        bhook.c
+ * PURPOSE:     Blocking Hook support for 1.x clients
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSACancelBlockingCall(VOID)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("WSACancelBlockingCall\n");
+
+    /* Call the prolog */
+    ErrorCode = WsApiProlog(&Process, &Thread);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Fail */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Make sure this isn't a 2.2 client */
+    if (LOBYTE(Process->Version) >= 2)
+    {
+        /* Only valid for 1.x */
+        SetLastError(WSAEOPNOTSUPP);
+        return SOCKET_ERROR;
+    }
+
+    /* Cancel the call */
+    ErrorCode = WsThreadCancelBlockingCall(Thread);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Fail */
+        SetLastError(ErrorCode);
+        return ErrorCode;
+    }
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSAIsBlocking(VOID)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("WSAIsBlocking\n");
+
+    /* Call the prolog */
+    ErrorCode = WsApiProlog(&Process, &Thread);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Fail unless its because we're busy */
+        if (ErrorCode != WSAEINPROGRESS) return FALSE;
+    }
+
+    /* Return the value from the thread */
+    return Thread->Blocking;
+}
+
+/*
+ * @implemented
+ */
+FARPROC
+WSAAPI
+WSASetBlockingHook(IN FARPROC lpBlockFunc)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("WSASetBlockingHook: %p\n", lpBlockFunc);
+
+    /* Call the prolog */
+    ErrorCode = WsApiProlog(&Process, &Thread);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Fail */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Make sure this isn't a 2.2 client */
+    if (LOBYTE(Process->Version) >= 2)
+    {
+        /* Only valid for 1.x */
+        SetLastError(WSAEOPNOTSUPP);
+        return NULL;
+    }
+
+    /* Make sure the pointer is safe */
+    if (IsBadCodePtr(lpBlockFunc))
+    {
+        /* Invalid pointer */
+        SetLastError(WSAEFAULT);
+        return NULL;
+    }
+
+    /* Set the blocking hook and return the previous one */
+    return WsThreadSetBlockingHook(Thread, lpBlockFunc);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAUnhookBlockingHook(VOID)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("WSAUnhookBlockingHook\n");
+
+    /* Call the prolog */
+    ErrorCode = WsApiProlog(&Process, &Thread);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* Fail */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Make sure this isn't a 2.2 client */
+    if (LOBYTE(Process->Version) >= 2)
+    {
+        /* Only valid for 1.x */
+        SetLastError(WSAEOPNOTSUPP);
+        return SOCKET_ERROR;
+    }
+
+    /* Set the blocking hook and return the previous one */
+    return WsThreadUnhookBlockingHook(Thread);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dcatalog.c b/reactos/dll/win32/ws2_32_new/src/dcatalog.c
new file mode 100644 (file)
index 0000000..2d7d714
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dcatalog.c
+ * PURPOSE:     Transport Catalog Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+#define TCCATALOG_NAME "Protocol_Catalog9"
+
+#define WsTcLock()          EnterCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+#define WsTcUnlock()        LeaveCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+
+/* FUNCTIONS *****************************************************************/
+
+PTCATALOG
+WSAAPI
+WsTcAllocate(VOID)
+{
+    PTCATALOG Catalog;
+    
+    /* Allocate the object */
+    Catalog = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Catalog));
+
+    /* Return it */
+    return Catalog;
+}
+
+BOOL
+WSAAPI
+WsTcOpen(IN PTCATALOG Catalog,
+         IN HKEY ParentKey)
+{
+    INT ErrorCode;
+    DWORD CreateDisposition;
+    HKEY CatalogKey, NewKey;
+    //DWORD CatalogEntries = 0;
+    DWORD RegType = REG_DWORD;
+    DWORD RegSize = sizeof(DWORD);
+    DWORD UniqueId = 0;
+    DWORD NewData = 0;
+
+    /* Initialize the catalog lock and namespace list */
+    InitializeCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+    InitializeListHead(&Catalog->ProtocolList);
+
+    /* Open the Catalog Key */
+    ErrorCode = RegOpenKeyEx(ParentKey,
+                             TCCATALOG_NAME,
+                             0,
+                             MAXIMUM_ALLOWED,
+                             &CatalogKey);
+
+    /* If we didn't find the key, create it */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Fake that we opened an existing key */
+        CreateDisposition = REG_OPENED_EXISTING_KEY;
+    }
+    else if (ErrorCode == ERROR_FILE_NOT_FOUND)
+    {
+        /* Create the Catalog Name */
+        ErrorCode = RegCreateKeyEx(ParentKey,
+                                   TCCATALOG_NAME,
+                                   0,
+                                   NULL,
+                                   REG_OPTION_NON_VOLATILE,
+                                   KEY_ALL_ACCESS,
+                                   NULL,
+                                   &CatalogKey,
+                                   &CreateDisposition);
+    }
+
+    /* Fail if that didn't work */
+    if (ErrorCode != ERROR_SUCCESS) return FALSE;
+
+    /* Check if we had to create the key */
+    if (CreateDisposition == REG_CREATED_NEW_KEY)
+    {
+        /* Write the count of entries (0 now) */
+        ErrorCode = RegSetValueEx(CatalogKey,
+                                  "Num_Catalog_Entries",
+                                  0,
+                                  REG_DWORD,
+                                  (LPBYTE)&NewData,
+                                  sizeof(NewData));
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Write the first catalog entry ID */
+        NewData = 1001;
+        ErrorCode = RegSetValueEx(CatalogKey,
+                                  "Next_Catalog_Entry_ID",
+                                  0,
+                                  REG_DWORD,
+                                  (LPBYTE)&NewData,
+                                  sizeof(NewData));
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Write the first catalog entry Uniqe ID */
+        NewData = 1;
+        ErrorCode = RegSetValueEx(CatalogKey,
+                                  "Serial_Access_Num",
+                                  0,
+                                  REG_DWORD,
+                                  (LPBYTE)&NewData,
+                                  sizeof(NewData));
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Create a key for this entry */
+        ErrorCode = RegCreateKeyEx(CatalogKey,
+                                   "Catalog_Entries",
+                                   0,
+                                   NULL,
+                                   REG_OPTION_NON_VOLATILE,
+                                   KEY_ALL_ACCESS,
+                                   NULL,
+                                   &NewKey,
+                                   &CreateDisposition);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Close the key since we don't need it */
+        RegCloseKey(NewKey);
+    }
+    else
+    {
+        /* Read the serial number */
+        ErrorCode = RegQueryValueEx(CatalogKey,
+                                    "Serial_Access_Num",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&UniqueId,
+                                    &RegSize);
+
+        /* Check if it's missing for some reason */
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Write the first catalog entry Unique ID */
+            NewData = 1;
+            ErrorCode = RegSetValueEx(CatalogKey,
+                                      "Serial_Access_Num",
+                                      0,
+                                      REG_DWORD,
+                                      (LPBYTE)&NewData,
+                                      sizeof(NewData));
+        }
+    }
+
+    /* Set the Catalog Key */
+    Catalog->CatalogKey = CatalogKey;
+    return TRUE;
+}
+
+DWORD
+WSAAPI
+WsTcInitializeFromRegistry(IN PTCATALOG Catalog,
+                           IN HKEY ParentKey,
+                           IN HANDLE CatalogEvent)
+{
+    INT ErrorCode = WSASYSCALLFAILURE;
+
+    /* Open the catalog */
+    if (WsTcOpen(Catalog, ParentKey))
+    {
+        /* Refresh it */
+        ErrorCode = WsTcRefreshFromRegistry(Catalog, CatalogEvent);
+    }
+
+    /* Return the status */
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsTcRefreshFromRegistry(IN PTCATALOG Catalog,
+                        IN HANDLE CatalogEvent)
+{
+    INT ErrorCode;
+    BOOLEAN LocalEvent = FALSE;
+    LIST_ENTRY LocalList;
+    DWORD UniqueId;
+    HKEY EntriesKey;
+    DWORD CatalogEntries;
+    PTCATALOG_ENTRY CatalogEntry;
+    DWORD NextCatalogEntry;
+    BOOL NewChangesMade;
+    PLIST_ENTRY Entry;
+    DWORD RegType = REG_DWORD;
+    DWORD RegSize = sizeof(DWORD);
+    DWORD i;
+
+    /* Check if we got an event */
+    if (!CatalogEvent)
+    {
+        /* Create an event ourselves */
+        CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!CatalogEvent) return WSASYSCALLFAILURE;
+        LocalEvent = TRUE;
+    }
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Initialize our local list for the loop */
+    InitializeListHead(&LocalList);
+
+    /* Start looping */
+    do
+    {
+        /* Setup notifications for the catalog entry */
+        ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey,
+                                             CatalogEvent,
+                                             &UniqueId);
+        if (ErrorCode != ERROR_SUCCESS) break;
+
+        /* Check if we've changed till now */
+        if (UniqueId == Catalog->UniqueId)
+        {
+            /* We haven't, so return */
+            ErrorCode = ERROR_SUCCESS;
+            break;
+        }
+
+        /* Now Open the Entries */
+        ErrorCode = RegOpenKeyEx(Catalog->CatalogKey,
+                                 "Catalog_Entries",
+                                 0,
+                                 MAXIMUM_ALLOWED,
+                                 &EntriesKey);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+        
+        /* Get the next entry */
+        ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
+                                    "Next_Catalog_Entry_ID",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&NextCatalogEntry,
+                                    &RegSize);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Find out how many there are */
+        ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
+                                    "Num_Catalog_Entries",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&CatalogEntries,
+                                    &RegSize);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Initialize them all */
+        for (i = 1; i <= CatalogEntries; i++) 
+        {
+            /* Allocate a Catalog Entry Structure */
+            CatalogEntry = WsTcEntryAllocate();
+            if (!CatalogEntry)
+            {
+                /* Not enough memory, fail */
+                ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+                break;
+            }
+
+            /* Initialize it from the Registry Key */
+            ErrorCode = WsTcEntryInitializeFromRegistry(CatalogEntry,
+                                                        EntriesKey,
+                                                        i);
+            if (ErrorCode != ERROR_SUCCESS)
+            {
+                /* We failed to get it, dereference the entry and leave */
+                WsTcEntryDereference(CatalogEntry);
+                break;
+            }
+
+            /* Insert it to our List */
+            InsertTailList(&LocalList, &CatalogEntry->CatalogLink);
+        }
+
+        /* Close the catalog key */
+        RegCloseKey(EntriesKey);
+
+        /* Check if we changed during our read and if we have success */
+        NewChangesMade = WsCheckCatalogState(CatalogEvent);
+        if (!NewChangesMade && ErrorCode == ERROR_SUCCESS)
+        {
+            /* All is good, update the protocol list */
+            WsTcUpdateProtocolList(Catalog, &LocalList);
+
+            /* Update and return */
+            Catalog->UniqueId = UniqueId;
+            Catalog->NextId = NextCatalogEntry;
+            break;
+        }
+
+        /* We failed and/or catalog data changed, free what we did till now */
+        while (!IsListEmpty(&LocalList))
+        {
+            /* Get the LP Catalog Item */
+            Entry = RemoveHeadList(&LocalList);
+            CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+            /* Dereference it */
+            WsTcEntryDereference(CatalogEntry);
+        }
+    } while (NewChangesMade);
+
+    /* Release the lock */
+    WsTcUnlock();
+
+    /* Close the event, if any was created by us */
+    if (LocalEvent) CloseHandle(CatalogEvent);
+
+    /* All Done */
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsTcGetEntryFromAf(IN PTCATALOG Catalog,
+                   IN INT AddressFamily,
+                   IN PTCATALOG_ENTRY *CatalogEntry)
+{
+    INT ErrorCode = WSAEINVAL;
+    PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
+    PTCATALOG_ENTRY Entry;
+
+    /* Assume failure */
+    *CatalogEntry = NULL;
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Match the Id with all the entries in the List */
+    while (NextEntry != &Catalog->ProtocolList)
+    {
+        /* Get the Current Entry */
+        Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
+        NextEntry = NextEntry->Flink;
+
+        /* Check if this is the Catalog Entry ID we want */
+        if (Entry->ProtocolInfo.iAddressFamily == AddressFamily)
+        {
+            /* Check if it doesn't already have a provider */
+            if (!Entry->Provider)
+            {
+                /* Match, load the Provider */
+                ErrorCode = WsTcLoadProvider(Catalog, Entry);
+
+                /* Make sure this didn't fail */
+                if (ErrorCode != ERROR_SUCCESS) break;
+            }
+
+            /* Reference the entry and return it */
+            InterlockedIncrement(&Entry->RefCount);
+            *CatalogEntry = Entry;
+            ErrorCode = ERROR_SUCCESS;
+            break;
+        }
+    }
+
+    /* Release the catalog */
+    WsTcUnlock();
+
+    /* Return */
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsTcGetEntryFromCatalogEntryId(IN PTCATALOG Catalog,
+                               IN DWORD CatalogEntryId,
+                               IN PTCATALOG_ENTRY *CatalogEntry)
+{
+    PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
+    PTCATALOG_ENTRY Entry;
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Match the Id with all the entries in the List */
+    while (NextEntry != &Catalog->ProtocolList)
+    {
+        /* Get the Current Entry */
+        Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
+        NextEntry = NextEntry->Flink;
+
+        /* Check if this is the Catalog Entry ID we want */
+        if (Entry->ProtocolInfo.dwCatalogEntryId == CatalogEntryId)
+        {
+            /* Check if it doesn't already have a provider */
+            if (!Entry->Provider)
+            {
+                /* Match, load the Provider */
+                WsTcLoadProvider(Catalog, Entry);
+            }
+
+            /* Reference the entry and return it */
+            InterlockedIncrement(&Entry->RefCount);
+            *CatalogEntry = Entry;
+            break;
+        }
+    }
+
+    /* Release the catalog */
+    WsTcUnlock();
+
+    /* Return */
+    return ERROR_SUCCESS;
+}
+
+DWORD
+WSAAPI
+WsTcGetEntryFromTriplet(IN PTCATALOG Catalog,
+                        IN INT af,
+                        IN INT type,
+                        IN INT protocol,
+                        IN DWORD StartId,
+                        IN PTCATALOG_ENTRY *CatalogEntry)
+{
+    INT ErrorCode = WSAEINVAL;
+    PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
+    PTCATALOG_ENTRY Entry;
+
+    /* Assume failure */
+    *CatalogEntry = NULL;
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Check if we are starting past 0 */
+    if (StartId)
+    {
+        /* Loop the list */
+        while (NextEntry != &Catalog->ProtocolList)
+        {
+            /* Get the Current Entry */
+            Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
+            NextEntry = NextEntry->Flink;
+
+            /* Check if this is the ID where we are starting */
+            if (Entry->ProtocolInfo.dwCatalogEntryId == StartId) break;
+        }
+    }
+
+    /* Match the Id with all the entries in the List */
+    while (NextEntry != &Catalog->ProtocolList)
+    {
+        /* Get the Current Entry */
+        Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
+        NextEntry = NextEntry->Flink;
+
+        /* Check if Address Family Matches or if it's wildcard */
+        if ((Entry->ProtocolInfo.iAddressFamily == af) || (af == AF_UNSPEC))
+        {    
+            /* Check if Socket Type Matches or if it's wildcard */
+            if ((Entry->ProtocolInfo.iSocketType == type) || (type == 0))
+            {
+                /* Check if Protocol is In Range or if it's wildcard */
+                if (((Entry->ProtocolInfo.iProtocol >= protocol) && 
+                    ((Entry->ProtocolInfo.iProtocol + 
+                      Entry->ProtocolInfo.iProtocolMaxOffset) <= protocol)) ||
+                    (protocol == 0))
+                {
+                    /* Check if it doesn't already have a provider */
+                    if (!Entry->Provider)
+                    {
+                        /* Match, load the Provider */
+                        ErrorCode = WsTcLoadProvider(Catalog, Entry);
+
+                        /* Make sure this didn't fail */
+                        if (ErrorCode != ERROR_SUCCESS) break;
+                    }
+
+                    /* Reference the entry and return it */
+                    InterlockedIncrement(&Entry->RefCount);
+                    *CatalogEntry = Entry;
+                    ErrorCode = ERROR_SUCCESS;
+                    break;
+                } 
+                else 
+                {
+                    ErrorCode = WSAEPROTONOSUPPORT;
+                }
+            } 
+            else 
+            {
+                ErrorCode = WSAESOCKTNOSUPPORT;
+            }
+        } 
+        else 
+        {
+            ErrorCode = WSAEAFNOSUPPORT;
+        }
+    }
+
+    /* Release the catalog */
+    WsTcUnlock();
+
+    /* Return */
+    return ErrorCode;
+}
+
+PTPROVIDER
+WSAAPI
+WsTcFindProvider(IN PTCATALOG Catalog,
+                 IN LPGUID ProviderId)
+{
+    PTPROVIDER Provider;
+    PLIST_ENTRY Entry;
+    PTCATALOG_ENTRY CatalogEntry;
+
+    /* Loop the provider list */
+    Entry = Catalog->ProtocolList.Flink;
+    while (Entry != &Catalog->ProtocolList)
+    {
+        /* Get the entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Move to the next one, get the provider */
+        Entry = Entry->Flink;
+        Provider = CatalogEntry->Provider;
+
+        /* Check for a match */
+        if ((Provider) &&
+            !(memcmp(&CatalogEntry->ProtocolInfo.ProviderId,
+                    ProviderId,
+                    sizeof(GUID))))
+        {
+            /* Found a match */
+            return Provider;
+        }
+    }
+
+    /* No match here */
+    return NULL;
+}
+
+DWORD
+WSAAPI
+WsTcLoadProvider(IN PTCATALOG Catalog,
+                 IN PTCATALOG_ENTRY CatalogEntry)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    PTPROVIDER Provider;
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Check if we have a provider already */
+    if (!CatalogEntry->Provider)
+    {
+        /* Try to find another instance */
+        Provider = WsTcFindProvider(Catalog,
+                                    &CatalogEntry->ProtocolInfo.ProviderId);
+
+        /* Check if we found one now */
+        if (Provider)
+        {
+            /* Set this one as the provider */
+            WsTcEntrySetProvider(CatalogEntry, Provider);
+            ErrorCode = ERROR_SUCCESS;
+        }
+        else
+        {
+            /* Nothing found, Allocate a provider */
+            if ((Provider = WsTpAllocate()))
+            {
+                /* Initialize it */
+                ErrorCode = WsTpInitialize(Provider,
+                                           CatalogEntry->DllPath,
+                                           &CatalogEntry->ProtocolInfo);
+
+                /* Ensure success */
+                if (ErrorCode == ERROR_SUCCESS)
+                {
+                    /* Set the provider */
+                    WsTcEntrySetProvider(CatalogEntry, Provider);
+                }
+
+                /* Dereference it */
+                WsTpDereference(Provider);
+            }
+            else
+            {
+                /* No memory */
+                ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            }
+        }
+    }
+
+    /* Release the lock */
+    WsTcUnlock();
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsTcUpdateProtocolList(IN PTCATALOG Catalog,
+                       IN PLIST_ENTRY List)
+{
+    LIST_ENTRY TempList;
+    PTCATALOG_ENTRY CatalogEntry, OldCatalogEntry;
+    PLIST_ENTRY Entry;
+
+    /* First move from our list to the old one */
+    InsertHeadList(&Catalog->ProtocolList, &TempList);
+    RemoveEntryList(&Catalog->ProtocolList);
+    InitializeListHead(&Catalog->ProtocolList);
+
+    /* Loop every item on the list */
+    while (!IsListEmpty(List))
+    {
+        /* Get the catalog entry */
+        Entry = RemoveHeadList(List);
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Check if this item is already on our list */
+        Entry = TempList.Flink;
+        while (Entry != &TempList)
+        {
+            /* Get the catalog entry */
+            OldCatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+            Entry = Entry->Flink;
+
+            /* Check if they match */
+            if (CatalogEntry->ProtocolInfo.dwCatalogEntryId ==
+                OldCatalogEntry->ProtocolInfo.dwCatalogEntryId)
+            {
+                /* We have a match, use the old item instead */
+                WsTcEntryDereference(CatalogEntry);
+                CatalogEntry = OldCatalogEntry;
+                RemoveEntryList(&CatalogEntry->CatalogLink);
+
+                /* Decrease the number of protocols we have */
+                Catalog->ItemCount--;
+                break;
+            }
+        }
+
+        /* Add this item */
+        InsertTailList(&Catalog->ProtocolList, &CatalogEntry->CatalogLink);
+        Catalog->ItemCount++;
+    }
+
+    /* If there's anything left on the temporary list */
+    while (!IsListEmpty(&TempList))
+    {
+        /* Get the entry */
+        Entry = RemoveHeadList(&TempList);
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Remove it */
+        Catalog->ItemCount--;
+        WsTcEntryDereference(CatalogEntry);
+    }
+}
+
+VOID
+WSAAPI
+WsTcEnumerateCatalogItems(IN PTCATALOG Catalog,
+                          IN PTCATALOG_ENUMERATE_PROC Callback,
+                          IN PVOID Context)
+{
+    PLIST_ENTRY Entry;
+    PTCATALOG_ENTRY CatalogEntry;
+    BOOL GoOn = TRUE;
+
+    /* Lock the catalog */
+    WsTcLock();
+
+    /* Loop the entries */
+    Entry = Catalog->ProtocolList.Flink;
+    while (GoOn && (Entry != &Catalog->ProtocolList))
+    {
+        /* Get the entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Move to the next one and call the callback */
+        Entry = Entry->Flink;
+        GoOn = Callback(Context, CatalogEntry);
+    }
+
+    /* Release lock */
+    WsTcUnlock();
+}
+
+DWORD
+WSAAPI
+WsTcFindIfsProviderForSocket(IN PTCATALOG Catalog,
+                             IN SOCKET Handle)
+{
+    PTPROVIDER Provider;
+    IN SOCKET NewHandle;
+    INT Error;
+    DWORD OptionLength;
+    PLIST_ENTRY Entry;
+    WSAPROTOCOL_INFOW ProtocolInfo;
+    DWORD UniqueId;
+    INT ErrorCode;
+    PTCATALOG_ENTRY CatalogEntry;
+
+    /* Get the catalog lock */
+    WsTcLock();
+
+    /* Loop as long as the catalog changes */
+CatalogChanged:
+
+    /* Loop every provider */
+    Entry = Catalog->ProtocolList.Flink;
+    while (Entry != &Catalog->ProtocolList)
+    {
+        /* Get the catalog entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Move to the next entry */
+        Entry = Entry->Flink;
+
+        /* Skip it if it doesn't support IFS */
+        if (!(CatalogEntry->ProtocolInfo.dwServiceFlags1 & XP1_IFS_HANDLES)) continue;
+
+        /* Check if we need to load it */
+        if (!(Provider = CatalogEntry->Provider))
+        {
+            /* Load it */
+            ErrorCode = WsTcLoadProvider(Catalog, CatalogEntry);
+            
+            /* Skip it if we failed to load it */
+            if (ErrorCode != ERROR_SUCCESS) continue;
+
+            /* Get the provider again */
+            Provider = CatalogEntry->Provider;
+        }
+
+        /* Reference the entry and get our unique id */
+        InterlockedIncrement(&CatalogEntry->RefCount);
+        UniqueId = Catalog->UniqueId;
+
+        /* Release the lock now */
+        WsTcUnlock();
+
+        /* Get the catalog entry ID */
+        OptionLength = sizeof(ProtocolInfo);
+        ErrorCode = Provider->Service.lpWSPGetSockOpt(Handle,
+                                                      SOL_SOCKET,
+                                                      SO_PROTOCOL_INFOW,
+                                                      (PCHAR)&ProtocolInfo,
+                                                      (LPINT)&OptionLength,
+                                                      &Error);
+
+        /* Dereference the entry and check the result */
+        WsTcEntryDereference(CatalogEntry);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Lock and make sure this provider is still valid */
+            WsTcLock();
+            if (UniqueId == Catalog->UniqueId) continue;
+
+            /* It changed! We need to start over */
+            goto CatalogChanged;
+        }
+
+        /* Now get the IFS handle */
+        NewHandle = WPUModifyIFSHandle(ProtocolInfo.dwCatalogEntryId,
+                                       Handle,
+                                       &Error);
+        
+        /* Check if the socket is invalid */
+        if (NewHandle == INVALID_SOCKET) return WSAENOTSOCK;
+
+        /* We suceeded, get out of here */
+        return ERROR_SUCCESS;
+    }
+
+    /* Unrecognized socket if we get here: note, we still have the lock */
+    WsTcUnlock();
+    return WSAENOTSOCK;
+}
+
+VOID
+WSAAPI
+WsTcRemoveCatalogItem(IN PTCATALOG Catalog,
+                      IN PTCATALOG_ENTRY Entry)
+{
+    /* Remove the entry from the list */
+    RemoveEntryList(&Entry->CatalogLink);
+
+    /* Decrease our count */
+    Catalog->ItemCount--;
+}
+
+VOID
+WSAAPI
+WsTcDelete(IN PTCATALOG Catalog)
+{
+    PLIST_ENTRY Entry;
+    PTCATALOG_ENTRY CatalogEntry;
+
+    /* Check if we're initialized */
+    if (!Catalog->ProtocolList.Flink) return;
+
+    /* Acquire lock */
+    WsTcLock();
+
+    /* Loop every entry */
+    Entry = Catalog->ProtocolList.Flink;
+    while (Entry != &Catalog->ProtocolList)
+    {
+        /* Get this entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
+
+        /* Remove it */
+        WsTcRemoveCatalogItem(Catalog, CatalogEntry);
+
+        /* Dereference it */
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Move to the next entry */
+        Entry = Catalog->ProtocolList.Flink;
+    }
+
+    /* Check if the catalog key is opened */
+    if (Catalog->CatalogKey)
+    {
+        /* Close it */
+        RegCloseKey(Catalog->CatalogKey);
+        Catalog->CatalogKey = NULL;
+    }
+
+    /* Release and delete the lock */
+    WsTcUnlock();
+    DeleteCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+
+    /* Delete the object */
+    HeapFree(WsSockHeap, 0, Catalog);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dcatitem.c b/reactos/dll/win32/ws2_32_new/src/dcatitem.c
new file mode 100644 (file)
index 0000000..f3324f7
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dcatitem.c
+ * PURPOSE:     Transport Catalog Entry Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PTCATALOG_ENTRY
+WSAAPI
+WsTcEntryAllocate(VOID)
+{
+    PTCATALOG_ENTRY CatalogEntry;
+
+    /* Allocate the catalog entry */
+    CatalogEntry = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*CatalogEntry));
+
+    /* Set the default non-null members */
+    CatalogEntry->RefCount = 1;
+
+    /* Return it */
+    return CatalogEntry;
+}
+
+VOID
+WSAAPI
+WsTcEntryDelete(IN PTCATALOG_ENTRY CatalogEntry)
+{
+    /* Check if a provider is loaded */
+    if (CatalogEntry->Provider)
+    {
+        /* Dereference it too */
+        WsTpDereference(CatalogEntry->Provider);
+        CatalogEntry->Provider = NULL;
+    }
+
+    /* Delete us */
+    HeapFree(WsSockHeap, 0, CatalogEntry);
+}
+
+VOID
+WSAAPI
+WsTcEntryDereference(IN PTCATALOG_ENTRY CatalogEntry)
+{
+    /* Dereference and check if it's now 0 */
+    if (!(InterlockedDecrement(&CatalogEntry->RefCount)))
+    {
+        /* We can delete the Provider now */
+        WsTcEntryDelete(CatalogEntry);
+    }
+}
+
+DWORD
+WSAAPI
+WsTcEntryInitializeFromRegistry(IN PTCATALOG_ENTRY CatalogEntry,
+                                IN HKEY ParentKey,
+                                IN DWORD UniqueId)
+{
+    CHAR CatalogEntryName[13];
+    DWORD RegSize;
+    DWORD RegType = REG_BINARY;
+    HKEY EntryKey;
+    DWORD Return;
+
+    /* Convert to a 00000xxx string */
+    sprintf(CatalogEntryName, "%0""12""lu", UniqueId);
+
+    /* Open the Entry */
+    Return = RegOpenKeyEx(ParentKey,
+                          CatalogEntryName,
+                          0,
+                          KEY_READ,
+                          &EntryKey);
+
+    /* Get Size of Catalog Entry Structure */
+    Return = RegQueryValueExW(EntryKey, 
+                              L"PackedCatalogItem",
+                              0,
+                              NULL,
+                              NULL,
+                              &RegSize);
+    
+    /* Read the Whole Catalog Entry Structure */
+    Return = RegQueryValueExW(EntryKey, 
+                              L"PackedCatalogItem",
+                              0,
+                              &RegType,
+                              (LPBYTE)&CatalogEntry->DllPath,
+                              &RegSize);
+
+    /* Done */
+    RegCloseKey(EntryKey);
+    return Return;
+}
+
+VOID
+WSAAPI
+WsTcEntrySetProvider(IN PTCATALOG_ENTRY Entry,
+                     IN PTPROVIDER Provider)
+{
+    /* Reference the provider */
+    InterlockedIncrement(&Provider->RefCount);
+
+    /* Set it */
+    Entry->Provider = Provider;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dllmain.c b/reactos/dll/win32/ws2_32_new/src/dllmain.c
new file mode 100644 (file)
index 0000000..9c6d7ce
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dllmain.c
+ * PURPOSE:     DLL Entrypoint
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/*
+ * BUGS:
+ *       - GetAddrInfoW is completely IPv4 hacked and has some dirty code.
+ *       - LookupNodeByAddr is missing some IPv6 support.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+HANDLE WsSockHeap;
+HINSTANCE WsDllHandle;
+DWORD GlobalTlsIndex;
+
+/* FUNCTIONS *****************************************************************/
+
+BOOL
+APIENTRY
+DllMain(HANDLE hModule,
+        DWORD dwReason,
+        LPVOID lpReserved)
+{
+    PWSPROCESS WsProcess;
+
+    /* Main Entrypoint */
+    switch (dwReason) 
+    {
+        case DLL_PROCESS_ATTACH:
+
+            /* Save DLL Handle */
+            WsDllHandle = hModule;
+
+            /* Get Global Heap */
+            WsSockHeap = GetProcessHeap();
+
+            /* TLS Allocation */
+            GlobalTlsIndex = TlsAlloc();
+            if (GlobalTlsIndex == TLS_OUT_OF_INDEXES) return FALSE;
+
+            /* Initialize some critical sections */
+            WsCreateStartupSynchronization();
+            WsAsyncGlobalInitialize();
+            WsRasInitializeAutodial();
+            break;
+
+        case DLL_THREAD_ATTACH:
+            break;
+
+        case DLL_THREAD_DETACH:
+            /* Destroy the attached Winsock Thread */
+            WsThreadDestroyCurrentThread();
+            break;
+
+        case DLL_PROCESS_DETACH:
+
+            /* Make sure we were initialized */
+            if (!WsDllHandle) break;
+
+            /* Check if this was a FreeLibrary call (ie: not process cleanup) */
+            if (lpReserved)
+            {
+                /* Destroy the thread which is exiting */
+                WsThreadDestroyCurrentThread();
+
+                /* Check if we have a process and destroy it */
+                WsProcess = WsGetProcess();
+                if (WsProcess) WsProcDelete(WsProcess);
+
+                /* Cleanup the Thread and Socket managers */
+                WsThreadCleanup();
+                WsSockCleanup();
+
+                /* Cleanup critical sections */
+                WsDestroyStartupSynchronization();
+                WsAsyncGlobalTerminate();
+
+                /* Free the TLS Index */
+                TlsFree(GlobalTlsIndex);
+            }
+
+            /* Cleanup RAS auto-dial helper */
+            WsRasUninitializeAutodial();
+
+            /* Clear our handle */
+            WsDllHandle = NULL;
+            break;
+    }
+
+    /* Return to OS */
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAGetLastError(VOID)
+{
+    /* Let the Windows Function do the work */
+    return GetLastError();
+}
+
+/*
+ * @implemented
+ */
+VOID
+WSAAPI
+WSASetLastError(IN INT iError)
+{
+    /* Let the Windows Function do the work */
+    SetLastError(iError);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dprocess.c b/reactos/dll/win32/ws2_32_new/src/dprocess.c
new file mode 100644 (file)
index 0000000..0b7f188
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dprocess.c
+ * PURPOSE:     Process Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+PWSPROCESS CurrentWsProcess;
+
+#define WsProcLock()      EnterCriticalSection((LPCRITICAL_SECTION)&Process->ThreadLock);
+#define WsProcUnlock()    LeaveCriticalSection((LPCRITICAL_SECTION)&Process->ThreadLock);
+
+/* FUNCTIONS *****************************************************************/
+
+INT
+WSAAPI
+WsProcInitialize(IN PWSPROCESS Process)
+{
+    INT ErrorCode = WSAEFAULT;
+    HKEY RootKey = NULL;
+
+    /* Initialize the thread list lock */
+    InitializeCriticalSection((LPCRITICAL_SECTION)&Process->ThreadLock);
+    Process->LockReady = TRUE;
+
+    /* Open the Winsock Key */
+    RootKey = WsOpenRegistryRoot();
+
+    /* Create the LP Catalog change event and catalog */
+    Process->ProtocolCatalogEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    Process->ProtocolCatalog = WsTcAllocate();
+
+    /* Initialize it */
+    WsTcInitializeFromRegistry(Process->ProtocolCatalog,
+                               RootKey,
+                               Process->ProtocolCatalogEvent);
+
+    /* Create the NS Catalog change event and catalog */
+    Process->NamespaceCatalogEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    Process->NamespaceCatalog = WsNcAllocate();
+
+    /* Initialize it */
+    ErrorCode = WsNcInitializeFromRegistry(Process->NamespaceCatalog,
+                                           RootKey,
+                                           Process->NamespaceCatalogEvent);
+
+    /* Close the root key */
+    RegCloseKey(RootKey);
+    return ErrorCode;
+}
+
+PWSPROCESS
+WSAAPI
+WsProcAllocate(VOID)
+{
+    PWSPROCESS Process;
+
+    /* Allocate the structure */
+    Process = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Process));
+
+    /* Set default non-zero values */
+    Process->Version = MAKEWORD(2,2);
+
+    /* Return it */
+    return Process;
+}
+
+INT
+WSAAPI
+WsProcOpenAsyncHelperDevice(IN PWSPROCESS Process,
+                            OUT PHANDLE Handle)
+{
+    INT ErrorCode = WSASYSCALLFAILURE;
+
+    /* Lock the process */
+    WsProcLock();
+
+    /* Check if we have a handle, and if not, create one */
+    if ((Process->ApcHelper) ||
+        (WahOpenApcHelper(&Process->ApcHelper) == ERROR_SUCCESS))
+    {
+        /* Return the handle */
+        *Handle = Process->ApcHelper;
+        ErrorCode = ERROR_SUCCESS;
+    }
+
+    /* Unload the process and return */
+    WsProcUnlock();
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WsProcGetAsyncHelper(IN PWSPROCESS Process,
+                     OUT PHANDLE Handle)
+{
+    /* Check if we have it already set up */
+    if (Process->ApcHelper)
+    {
+        /* Just return it */
+        *Handle = Process->ApcHelper;
+        return ERROR_SUCCESS;
+    }
+    else
+    {
+        /* Open it for the first time */
+        return WsProcOpenAsyncHelperDevice(Process, Handle);
+    }
+}
+
+INT
+WSAAPI
+WsProcStartup(VOID)
+{
+    INT ErrorCode = WSAEFAULT;
+
+    /* Create a new process */
+    CurrentWsProcess = WsProcAllocate();
+
+    /* Initialize it */
+    if (CurrentWsProcess)
+    {
+        /* Initialize the process */
+        ErrorCode = WsProcInitialize(CurrentWsProcess);
+    }
+    else
+    {
+        /* No memory for the process object */
+        ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+    }
+
+    return ErrorCode;
+}
+
+PTCATALOG
+WSAAPI
+WsProcGetTCatalog(IN PWSPROCESS Process)
+{
+    /* Check if the catalogs have been modified */
+    if (WsCheckCatalogState(Process->ProtocolCatalogEvent))
+    {
+        /* Modification happened, reload them */
+        WsTcRefreshFromRegistry(Process->ProtocolCatalog,
+                                Process->ProtocolCatalogEvent);
+    }
+
+    /* Return it */
+    return Process->ProtocolCatalog;
+}
+
+PNSCATALOG
+WSAAPI
+WsProcGetNsCatalog(IN PWSPROCESS Process)
+{
+    /* Check if the catalogs have been modified */
+    if (WsCheckCatalogState(Process->NamespaceCatalogEvent))
+    {
+        /* Modification happened, reload them */
+        WsNcRefreshFromRegistry(Process->NamespaceCatalog,
+                                Process->NamespaceCatalogEvent);
+    }
+
+    /* Return it */
+    return Process->NamespaceCatalog;
+}
+
+BOOL
+WSAAPI
+WsProcDetachSocket(IN PWSPROCESS Process,
+                   IN PWAH_HANDLE Handle)
+{
+    PWSSOCKET Socket = (PWSSOCKET)Handle;
+
+    /* Disassociate this socket from the table */
+    WahRemoveHandleContext(WsSockHandleTable, Handle);
+
+    /* If this is isn't an IFS socket */
+    if (!Socket->Provider)
+    {
+        /* Check if we have an active handle helper */
+        if (Process->HandleHelper)
+        {
+            /* Close it */
+            WahCloseSocketHandle(Process->HandleHelper, (SOCKET)Socket->Handle);
+        }
+    }
+
+    /* Remove a reference and return */
+    WsSockDereference(Socket);
+    return TRUE;
+}
+
+BOOL
+WSAAPI
+CleanupNamespaceProviders(IN PVOID Callback,
+                          IN PNSCATALOG_ENTRY Entry)
+{
+    PNS_PROVIDER Provider;
+
+    /* Get the provider */
+    Provider = Entry->Provider;
+    if (Provider)
+    {
+        /* Do cleanup */
+        WsNpNSPCleanup(Provider);
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+BOOL
+WSAAPI
+CleanupProtocolProviders(IN PVOID Callback,
+                         IN PTCATALOG_ENTRY Entry)
+{
+    PTPROVIDER Provider;
+    INT ErrorCode;
+
+    /* Get the provider */
+    Provider = Entry->Provider;
+    if (Provider)
+    {
+        /* Do cleanup */
+        WsTpWSPCleanup(Provider, &ErrorCode);
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WSAAPI
+WsProcDelete(IN PWSPROCESS Process)
+{
+    /* Check if we didn't even initialize yet */
+    if (!Process->LockReady) return;
+
+    /* No more current process */
+    CurrentWsProcess = NULL;
+
+    /* If we have a socket table */
+    if (WsSockHandleTable)
+    {
+        /* Enumerate the sockets with a delete callback */
+        WahEnumerateHandleContexts(WsSockHandleTable,
+                                   WsSockDeleteSockets,
+                                   Process);
+    }
+
+    /* Close APC Helper */
+    if (Process->ApcHelper) WahCloseApcHelper(Process->ApcHelper);
+
+    /* Close handle helper */
+    if (Process->HandleHelper) WahCloseHandleHelper(Process->HandleHelper);
+
+    /* Check for notification helper */
+    if (Process->NotificationHelper)
+    {
+        /* Close notification helper */
+        WahCloseNotificationHandleHelper(Process->NotificationHelper);
+    }
+
+    /* Check if we have a protocol catalog*/
+    if (Process->ProtocolCatalog)
+    {
+        /* Enumerate it to clean it up */
+        WsTcEnumerateCatalogItems(Process->ProtocolCatalog,
+                                  CleanupProtocolProviders,
+                                  NULL);
+
+        /* Delete it */
+        WsTcDelete(Process->ProtocolCatalog);
+        Process->ProtocolCatalog = NULL;
+    }
+
+    /* Check if we have a namespace catalog*/
+    if (Process->NamespaceCatalog)
+    {
+        /* Enumerate it to clean it up */
+        WsNcEnumerateCatalogItems(Process->NamespaceCatalog,
+                                  CleanupNamespaceProviders,
+                                  NULL);
+
+        /* Delete it */
+        WsNcDelete(Process->NamespaceCatalog);
+        Process->NamespaceCatalog = NULL;
+    }
+
+    /* Delete the thread lock */
+    DeleteCriticalSection((LPCRITICAL_SECTION)&Process->ThreadLock);
+}
+
+VOID
+WSAAPI
+WsProcSetVersion(IN PWSPROCESS Process,
+                 IN WORD VersionRequested)
+{
+    WORD Major, Minor;
+    WORD OldMajor, OldMinor;
+
+    /* Get the version data */
+    Major = LOBYTE(VersionRequested);
+    Minor = HIBYTE(VersionRequested);
+    OldMajor = LOBYTE(Process->Version);
+    OldMinor = HIBYTE(Process->Version);
+
+    /* Check if we're going lower */
+    if ((Major < OldMajor) || ((Major == OldMajor) && (Minor < OldMinor)))
+    {
+        /* Set the new version */
+        Process->Version = VersionRequested;
+    }
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dprovide.c b/reactos/dll/win32/ws2_32_new/src/dprovide.c
new file mode 100644 (file)
index 0000000..8c09f9b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dprovide.c
+ * PURPOSE:     Transport Provider Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* FUNCTIONS *****************************************************************/
+
+PTPROVIDER
+WSAAPI
+WsTpAllocate(VOID)
+{
+    PTPROVIDER Provider;
+    
+    /* Allocate the object */
+    Provider = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Provider));
+
+    /* Setup non-zero data */
+    Provider->RefCount = 1;
+    
+    /* Return it */
+    return Provider;
+}
+
+DWORD
+WSAAPI
+WsTpInitialize(IN PTPROVIDER Provider,
+               IN LPSTR DllName,
+               IN LPWSAPROTOCOL_INFOW ProtocolInfo)
+{
+    WORD VersionRequested = MAKEWORD(2,2);
+    WSPUPCALLTABLE UpcallTable;
+    LPWSPSTARTUP WSPStartupProc;
+    WSPDATA WspData;
+    CHAR ExpandedDllPath[MAX_PATH];
+    
+    /* Clear the tables */
+    RtlZeroMemory(&UpcallTable, sizeof(UpcallTable));
+    RtlZeroMemory(&Provider->Service.lpWSPAccept, sizeof(WSPPROC_TABLE));
+
+    /* Set up the Upcall Table */
+    UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
+    UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
+    UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
+    UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
+    UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
+    UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
+    UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
+    UpcallTable.lpWPUPostMessage = WPUPostMessage;
+    UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
+    UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
+    UpcallTable.lpWPUQueueApc = WPUQueueApc;
+    UpcallTable.lpWPUResetEvent = WPUResetEvent;
+    UpcallTable.lpWPUSetEvent = WPUSetEvent;
+    UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
+    UpcallTable.lpWPUCloseThread = WPUCloseThread;
+
+    /* Expand the DLL Path */
+    ExpandEnvironmentStrings(DllName, ExpandedDllPath, MAX_PATH);
+
+    /* Load the DLL */
+    Provider->DllHandle = LoadLibrary(ExpandedDllPath);
+
+    /* Get the pointer to WSPStartup */
+    WSPStartupProc = (LPWSPSTARTUP)GetProcAddress(Provider->DllHandle, "WSPStartup");
+
+    /* Call it */
+    (*WSPStartupProc)(VersionRequested,
+                      &WspData,
+                      ProtocolInfo,
+                      UpcallTable,
+                      (LPWSPPROC_TABLE)&Provider->Service.lpWSPAccept);
+
+    /* Return */
+    return ERROR_SUCCESS;
+}
+
+DWORD
+WSAAPI
+WsTpWSPCleanup(IN PTPROVIDER Provider,
+               IN LPINT lpErrNo)
+{
+    LPWSPCLEANUP WSPCleanup = NULL;
+    INT ErrorCode = ERROR_SUCCESS;
+    
+    /* Make sure we have a loaded handle */
+    if (Provider->DllHandle)
+    {
+        /* Get the pointer and clear it */
+        WSPCleanup = InterlockedExchangePointer((PVOID*)&Provider->Service.lpWSPCleanup,
+                                                NULL);
+        /* If it's not NULL, call it */
+        if (WSPCleanup) ErrorCode = WSPCleanup(lpErrNo);
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsTpDelete(IN PTPROVIDER Provider)
+{
+    INT ErrorCode;
+    
+    /* Make sure we have a loaded handle */
+    if (Provider->DllHandle)
+    {
+        /* Clean us up */
+        WsTpWSPCleanup(Provider, &ErrorCode);
+
+        /* Unload the library */
+        FreeLibrary(Provider->DllHandle);
+
+        /* Clear the handle value */
+        Provider->DllHandle = NULL;
+    }
+}
+
+VOID
+WSAAPI
+WsTpDereference(IN PTPROVIDER Provider)
+{
+    /* Decrease the reference count and check if it's zero */
+    if (!InterlockedDecrement(&Provider->RefCount))
+    {
+        /* Delete us*/
+        WsTpDelete(Provider);
+    }
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dsocket.c b/reactos/dll/win32/ws2_32_new/src/dsocket.c
new file mode 100644 (file)
index 0000000..62c001f
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dsocket.c
+ * PURPOSE:     Socket Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+PWAH_HANDLE_TABLE WsSockHandleTable;
+
+/* FUNCTIONS *****************************************************************/
+
+INT
+WSAAPI
+WsSockStartup(VOID)
+{
+    /* Check if we have a socket table */
+    if (!WsSockHandleTable)
+    {
+        /* Create it */
+        return WahCreateHandleContextTable(&WsSockHandleTable);
+    }
+
+    /* Nothing to do */
+    return NO_ERROR;
+}
+
+VOID
+WSPAPI
+WsSockCleanup(VOID)
+{
+    /* Check if we have a socket table */
+    if (WsSockHandleTable)
+    {
+        /* Destroy it */
+        WahDestroyHandleContextTable(WsSockHandleTable);
+    }
+}
+
+PWSSOCKET
+WSAAPI
+WsSockAllocate(VOID)
+{
+    PWSSOCKET Socket;
+
+    /* Allocate the socket object */
+    Socket = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(WSSOCKET));
+
+    /* Setup default non-zero values */
+    Socket->RefCount = 2;
+    Socket->Overlapped = TRUE;
+
+    /* Return it */
+    return Socket;
+}
+
+INT
+WSAAPI
+WsSockInitialize(IN PWSSOCKET Socket,
+                 IN PTCATALOG_ENTRY CatalogEntry)
+{
+    PWSTHREAD CurrentThread;
+
+    /* Associate this catalog and reference it */
+    Socket->CatalogEntry = CatalogEntry;
+    InterlockedIncrement(&CatalogEntry->RefCount);
+
+    /* Associate the Provider and Process Objects */
+    Socket->Provider = CatalogEntry->Provider;
+
+    /* Get the current Thread Object */
+    if ((CurrentThread = TlsGetValue(TlsIndex)))
+    {
+        /* Set the overlapped mode */
+        Socket->Overlapped = (CurrentThread->OpenType == 0);
+    }
+
+    /* Return status */
+    return ERROR_SUCCESS;
+}
+
+PWSSOCKET
+WSAAPI
+WsSockGetSocketNoExport(IN SOCKET Handle)
+{
+    /* Let WAH do the translation */
+    return (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable,
+                                                  (HANDLE)Handle);
+}
+
+PWSSOCKET
+WSAAPI
+WsSockFindIfsSocket(IN SOCKET Handle)
+{
+    INT ErrorCode;
+    DWORD Flags;
+    PWSSOCKET Socket = NULL;
+    PWSPROCESS Process = NULL;
+    PTCATALOG Catalog = NULL;
+
+    /* Validate the socket and get handle info */
+    if ((Handle != INVALID_SOCKET) &&
+        (GetHandleInformation((HANDLE)Handle, &Flags)))
+    {
+        /* Get the process */
+        if ((Process = WsGetProcess()))
+        {
+            /* Get the catalog */
+            Catalog = WsProcGetTCatalog(Process);
+
+            /* Get the IFS Provider */
+            ErrorCode = WsTcFindIfsProviderForSocket(Catalog, Handle);
+
+            /* Check for success */
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* Get the Socket now */
+                Socket = WsSockGetSocketNoExport(Handle);
+
+                /* Mark it as an API Socket */
+                if (Socket) Socket->ApiSocket = TRUE;
+            }
+        }
+    }
+
+    /* Return the socket */
+    return Socket;
+}
+
+PWSSOCKET
+WSAAPI
+WsSockGetSocket(IN SOCKET Handle)
+{
+    PWSSOCKET Socket;
+
+    /* Let WAH do the translation */
+    if ((Socket = (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable,
+                                                         (HANDLE)Handle)))
+    {
+        return Socket;
+    }
+    else
+    {
+        /* WAH didn't find it, use IFS */
+        return WsSockFindIfsSocket(Handle);
+    }
+}
+
+INT
+WSAAPI
+WsSockAddApiReference(IN SOCKET Handle)
+{
+    PWSSOCKET Socket;
+
+    /* Get the Socket now */
+    if ((Socket = WsSockGetSocketNoExport(Handle)))
+    {
+        /* Mark it as an API Socket */
+        if (Socket) Socket->ApiSocket = TRUE;
+
+        /* Remove a reference and return */
+        WsSockDereference(Socket);
+        return ERROR_SUCCESS;
+    }
+
+    /* Return error */
+    return WSASYSCALLFAILURE;
+}
+
+BOOL
+WSAAPI
+WsSockDeleteSockets(IN LPVOID Context,
+                    IN PWAH_HANDLE Handle)
+{
+    /* Call the detach routine */
+    return WsProcDetachSocket((PWSPROCESS)Context, Handle);
+}
+
+VOID
+WSAAPI
+WsSockDelete(IN PWSSOCKET Socket)
+{
+    /* Check if we have a catalog entry */
+    if (Socket->CatalogEntry)
+    {
+        /* Dereference it */
+        WsTcEntryDereference(Socket->CatalogEntry);
+        Socket->CatalogEntry = NULL;
+    }
+}
+
+VOID
+WSAAPI
+WsSockDereference(IN PWSSOCKET Socket)
+{
+    /* Dereference and check if it's now 0 */
+    if (!(InterlockedDecrement(&Socket->RefCount)))
+    {
+        /* We can delete the Provider now */
+        WsSockDelete(Socket);
+    }
+}
+
+INT
+WSAAPI
+WsSockDisassociateHandle(IN PWSSOCKET Socket)
+{
+    /* Remove it from the list */
+    return WahRemoveHandleContext(WsSockHandleTable, (PWAH_HANDLE)Socket);
+}
+
+INT
+WSAAPI
+WsSockAssociateHandle(IN PWSSOCKET Socket,
+                      IN SOCKET Handle,
+                      IN BOOLEAN IsProvider)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    PWSSOCKET OldSocket;
+
+    /* Save the socket and provider */
+    Socket->IsProvider = IsProvider;
+    Socket->Handle = (HANDLE)Handle;
+
+    /* Insert it into the handle table */
+    OldSocket = (PWSSOCKET)WahInsertHandleContext(WsSockHandleTable,
+                                                  (PWAH_HANDLE)Socket);
+
+    /* Check if a socket already existed */
+    if (OldSocket != Socket)
+    {
+        /* We'll dereference it */
+        WsSockDereference(OldSocket);
+    }
+    else if (!OldSocket)
+    {
+        /* No memory to allocate it */
+        ErrorCode = WSAENOBUFS;
+    }
+
+    /* Return */
+    return ErrorCode;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/dthread.c b/reactos/dll/win32/ws2_32_new/src/dthread.c
new file mode 100644 (file)
index 0000000..1534f8d
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dprocess.c
+ * PURPOSE:     Thread Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+DWORD TlsIndex;
+
+/* FUNCTIONS *****************************************************************/
+
+DWORD
+WSAAPI
+WsThreadDefaultBlockingHook(VOID)
+{
+    MSG Message;
+    BOOL GotMessage = FALSE;
+    
+    /* Get the message */
+    GotMessage = PeekMessage(&Message, NULL, 0, 0, PM_REMOVE);
+
+    /* Check if we got one */
+    if (GotMessage)
+    {
+        /* Process it */
+        TranslateMessage(&Message);
+        DispatchMessage(&Message);
+    }
+
+    /* return */
+    return GotMessage;
+}
+
+BOOL
+WSAAPI
+WsThreadBlockingCallback(IN DWORD_PTR Context)
+{
+    PWSTHREAD Thread = TlsGetValue(TlsIndex);
+
+    /* Set thread as blocking, set cancel callback and the clear cancel flag */
+    Thread->Blocking = TRUE;
+    Thread->CancelBlockingCall = (LPWSPCANCELBLOCKINGCALL)Context;
+    Thread->Cancelled = FALSE;
+
+    /* Call the blocking hook */
+    while(Thread->BlockingHook());
+
+    /* We're not blocking anymore */
+    Thread->Blocking = FALSE;
+
+    /* Return whether or not we were cancelled */
+    return !Thread->Cancelled;
+}
+
+FARPROC
+WSAAPI
+WsThreadSetBlockingHook(IN PWSTHREAD Thread,
+                        IN FARPROC BlockingHook)
+{
+    FARPROC OldHook = Thread->BlockingHook;
+
+    /* Check if we're resetting to our default hook */
+    if (BlockingHook == WsThreadDefaultBlockingHook)
+    {
+        /* Clear out the blocking callback */
+        Thread->BlockingCallback = NULL;
+    }
+    else
+    {
+        /* Set the blocking callback */
+        Thread->BlockingCallback = WsThreadBlockingCallback;
+    }
+
+    /* Set the new blocking hook and return the previous */
+    Thread->BlockingHook = BlockingHook;
+    return OldHook;
+}
+
+DWORD
+WSAAPI
+WsThreadUnhookBlockingHook(IN PWSTHREAD Thread)
+{
+    /* Reset the hook to the default, and remove the callback */
+    Thread->BlockingHook = WsThreadDefaultBlockingHook;
+    Thread->BlockingCallback = NULL;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+DWORD
+WSAAPI
+WsThreadCancelBlockingCall(IN PWSTHREAD Thread)
+{
+    INT ErrorCode, ReturnValue;
+
+    /* Make sure that the Thread is really in a blocking call */
+    if (!Thread->Blocking) return WSAEINVAL;
+
+    /* Make sure we haven't already been cancelled */
+    if (!Thread->Cancelled)
+    {
+        /* Call the cancel procedure */
+        ReturnValue = Thread->CancelBlockingCall(&ErrorCode);
+        if (ReturnValue != ERROR_SUCCESS) return ErrorCode;
+
+        /* Set us as cancelled */
+        Thread->Cancelled = TRUE;
+    }
+
+    /* Success */
+    return ERROR_SUCCESS;
+}
+
+PWSPROTO_BUFFER
+WSAAPI
+WsThreadGetProtoBuffer(IN PWSTHREAD Thread)
+{
+    /* See if it already exists */
+    if (!Thread->ProtocolInfo)
+    {
+        /* We don't have a buffer; allocate it */
+        Thread->ProtocolInfo = HeapAlloc(WsSockHeap, 0, sizeof(PWSPROTO_BUFFER));
+    }
+
+    /* Return it */
+    return Thread->ProtocolInfo;
+}
+
+PWSTHREAD
+WSAAPI
+WsThreadAllocate(VOID)
+{
+    PWSTHREAD Thread;
+    
+    /* Allocate the object */
+    Thread = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Thread));
+
+    /* Set non-zero data */
+    Thread->BlockingHook = WsThreadDefaultBlockingHook;
+
+    /* Return it */
+    return Thread;
+}
+
+DWORD
+WSAAPI
+WsThreadStartup(VOID)
+{
+    INT ErrorCode = WSASYSCALLFAILURE;
+    
+    /* Check if we have a valid TLS */
+    if (TlsIndex == TLS_OUT_OF_INDEXES)
+    {
+        /* Set the global one */
+        if ((TlsIndex = GlobalTlsIndex) != TLS_OUT_OF_INDEXES)
+        {
+            /* Success! */
+            ErrorCode = ERROR_SUCCESS;
+        }
+    }
+    else
+    {
+        /* TLS was already OK */
+        ErrorCode = ERROR_SUCCESS;
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsThreadCleanup(VOID)
+{
+    /* Check if we have a valid TLS */
+    if (TlsIndex != TLS_OUT_OF_INDEXES)
+    {
+        /* We do, invalidate it */
+        TlsIndex = TLS_OUT_OF_INDEXES;
+    }
+}
+
+DWORD
+WSAAPI
+WsThreadInitialize(IN PWSTHREAD Thread,
+                   IN PWSPROCESS Process)
+{
+    INT ErrorCode = WSASYSCALLFAILURE;
+    
+    /* Set the process */
+    Thread->Process = Process;
+
+    /* Get the helper device */
+    if ((WsProcGetAsyncHelper(Process, &Thread->AsyncHelper)) == ERROR_SUCCESS)
+    {
+        /* Initialize a WAH Thread ID */
+        if ((WahOpenCurrentThread(Thread->AsyncHelper,
+                                  &Thread->WahThreadId)) == ERROR_SUCCESS)
+        {
+            /* Success */
+            ErrorCode = ERROR_SUCCESS;
+        }
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsThreadDelete(IN PWSTHREAD Thread)
+{
+    /* Remove the blocking hook */
+    Thread->BlockingHook = NULL;
+
+    /* Free our buffers */
+    if (Thread->Hostent) HeapFree(WsSockHeap, 0, Thread->Hostent);
+    if (Thread->Servent) HeapFree(WsSockHeap, 0, Thread->Servent);
+    if (Thread->ProtocolInfo) HeapFree(WsSockHeap, 0, Thread->ProtocolInfo);
+
+    /* Clear the TLS */
+    TlsSetValue(TlsIndex, NULL);
+
+    /* Close the WAH Handle */
+    WahCloseThread(Thread->AsyncHelper, &Thread->WahThreadId);
+
+    /* Unlink the process and free us */
+    Thread->Process = NULL;
+    HeapFree(WsSockHeap, 0, Thread);
+}
+
+VOID
+WSAAPI
+WsThreadDestroyCurrentThread(VOID)
+{
+    PWSTHREAD Thread;
+
+    /* Make sure we have TLS */
+    if (TlsIndex != TLS_OUT_OF_INDEXES)
+    {
+        /* Get the thread */
+        if ((Thread = TlsGetValue(TlsIndex)))
+        {
+            /* Delete it */
+            WsThreadDelete(Thread);
+        }
+    }
+}
+
+DWORD
+WSAAPI
+WsThreadCreate(IN PWSPROCESS Process,
+               IN PWSTHREAD *CurrentThread)
+{
+    PWSTHREAD Thread = NULL;
+    INT ErrorCode = WSASYSCALLFAILURE;
+    
+    /* Make sure we have TLS */
+    if (TlsIndex != TLS_OUT_OF_INDEXES)
+    {
+        /* Allocate the thread */
+        if ((Thread = WsThreadAllocate()))
+        {
+            /* Initialize it */
+            if (WsThreadInitialize(Thread, Process) == ERROR_SUCCESS)
+            {
+                /* Set the TLS */
+                if (TlsSetValue(TlsIndex, Thread))
+                {
+                    /* Return it and success */
+                    *CurrentThread = Thread;
+                    ErrorCode = ERROR_SUCCESS;
+                }
+            }
+
+            /* Check for any failures */
+            if (ErrorCode != ERROR_SUCCESS) WsThreadDelete(Thread);
+        }
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsThreadGetCurrentThread(IN PWSPROCESS Process,
+                         IN PWSTHREAD *Thread)
+{
+    /* Get the thread */
+    if ((*Thread = TlsGetValue(TlsIndex)))
+    {
+        /* Success */
+        return ERROR_SUCCESS;
+    }
+    else
+    {
+        /* We failed, initialize it */
+        return WsThreadCreate(Process, Thread);
+    }
+}
+
+LPWSATHREADID
+WSAAPI
+WsThreadGetThreadId(IN PWSPROCESS Process)
+{
+    PWSTHREAD Thread;
+
+    /* Get the thread */
+    if ((Thread = TlsGetValue(TlsIndex)))
+    {
+        /* Return the ID */
+        return &Thread->WahThreadId;
+    }
+    else
+    {
+        /* Not a valid thread */
+        return NULL;
+    }
+}
+
+PHOSTENT
+WSAAPI
+WsThreadBlobToHostent(IN PWSTHREAD Thread,
+                      IN LPBLOB Blob)
+{
+    /* Check if our buffer is too small */
+    if (Thread->HostentSize < Blob->cbSize)
+    {
+        /* Delete the current buffer and allocate a new one */
+        HeapFree(WsSockHeap, 0, Thread->Hostent);
+        Thread->Hostent = HeapAlloc(WsSockHeap, 0, Blob->cbSize);
+
+        /* Set the new size */
+        Thread->HostentSize = Blob->cbSize;
+    }
+
+    /* Do we have a buffer? */
+    if (Thread->Hostent)
+    {
+        /* Copy the data inside */
+        RtlMoveMemory(Thread->Hostent, Blob->pBlobData, Blob->cbSize);
+    }
+    else
+    {
+        /* No buffer space! */
+        Thread->HostentSize = 0;
+        SetLastError(WSA_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the buffer */
+    return (PHOSTENT)Thread->Hostent;
+}
+
+PSERVENT
+WSAAPI
+WsThreadBlobToServent(IN PWSTHREAD Thread,
+                      IN LPBLOB Blob)
+{
+    /* Check if our buffer is too small */
+    if (Thread->ServentSize < Blob->cbSize)
+    {
+        /* Delete the current buffer and allocate a new one */
+        HeapFree(WsSockHeap, 0, Thread->Servent);
+        Thread->Servent = HeapAlloc(WsSockHeap, 0, Blob->cbSize);
+
+        /* Set the new size */
+        Thread->ServentSize = Blob->cbSize;
+    }
+
+    /* Do we have a buffer? */
+    if (Thread->Servent)
+    {
+        /* Copy the data inside */
+        RtlMoveMemory(Thread->Servent, Blob->pBlobData, Blob->cbSize);
+    }
+    else
+    {
+        /* No buffer space! */
+        Thread->ServentSize = 0;
+        SetLastError(WSA_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the buffer */
+    return (PSERVENT)Thread->Servent;
+}
+
diff --git a/reactos/dll/win32/ws2_32_new/src/dupsock.c b/reactos/dll/win32/ws2_32_new/src/dupsock.c
new file mode 100644 (file)
index 0000000..4167c7d
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        dupsock.c
+ * PURPOSE:     Socket Duplication
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSADuplicateSocketA(IN SOCKET s,
+                    IN DWORD dwProcessId,
+                    OUT LPWSAPROTOCOL_INFOA lpProtocolInfo)
+{
+    WSAPROTOCOL_INFOW ProtocolInfoW;
+    INT ErrorCode;
+    DPRINT("WSADuplicateSocketA: %lx, %lx, %p\n", s, dwProcessId, lpProtocolInfo);
+  
+    /* Call the Unicode Function */
+    ErrorCode = WSADuplicateSocketW(s, dwProcessId, &ProtocolInfoW);
+
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {                          
+        /* Convert Protocol Info to Ansi */
+        if (lpProtocolInfo) 
+        {    
+            /* Convert the information to ANSI */
+            ErrorCode = MapUnicodeProtocolInfoToAnsi(&ProtocolInfoW,
+                                                     lpProtocolInfo);
+        }
+        else
+        {
+            /* Fail */
+            ErrorCode = WSAEFAULT;
+        }
+
+        /* Check if the conversion failed */
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Set the last error and normalize the error */
+            SetLastError(ErrorCode);
+            ErrorCode = SOCKET_ERROR;
+        }
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSADuplicateSocketW(IN SOCKET s,
+                    IN DWORD dwProcessId,
+                    OUT LPWSAPROTOCOL_INFOW lpProtocolInfo)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSADuplicateSocketW: %lx, %lx, %p\n", s, dwProcessId, lpProtocolInfo);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPDuplicateSocket(s,
+                                                            dwProcessId,
+                                                            lpProtocolInfo,
+                                                            &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/enumprot.c b/reactos/dll/win32/ws2_32_new/src/enumprot.c
new file mode 100644 (file)
index 0000000..a4d18c9
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        enumprot.c
+ * PURPOSE:     Protocol Enumeration
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+BOOL
+WSAAPI
+CheckProtocolMatch(IN LPINT ProtocolSet,
+                   IN LPWSAPROTOCOL_INFOW ProtocolInfo)
+{
+    BOOL Return = FALSE;
+    DWORD i = 0;
+    INT ProtocolId = 0;
+
+    /* Make sure we have a set */
+    if (ProtocolSet)
+    {
+        /* Get the first ID */
+        ProtocolId = ProtocolSet[i];
+
+        /* Loop the list */
+        while (ProtocolId != 0)
+        {
+            /* Check if it's within ranges */
+            if ((ProtocolId >= ProtocolInfo->iProtocol) &&
+                (ProtocolId <= (ProtocolInfo->iProtocol +
+                                ProtocolInfo->iProtocolMaxOffset)))
+            {
+                /* Found it */
+                Return = TRUE;
+                break;
+            }
+
+            /* Move on */
+            i++;
+            ProtocolId = ProtocolSet[i];
+        }
+    }
+    else
+    {
+        /* Assume match */
+        Return = TRUE;
+    }
+
+    /* Return result */
+    return Return;
+}
+
+VOID
+WSAAPI
+ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo,
+                        IN PPROTOCOL_ENUM_CONTEXT Context)
+{
+    /* Check if we'll have space */
+    if ((Context->BufferUsed + sizeof(*ProtocolInfo)) <=
+        (Context->BufferLength))
+    {
+        /* Copy the data */
+        RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer +
+                              Context->BufferUsed),
+                      ProtocolInfo,
+                      sizeof(*ProtocolInfo));
+
+        /* Increase the count */
+        Context->Count++;
+    }
+}
+
+BOOL
+WSAAPI
+ProtocolEnumerationProc(PVOID EnumContext,
+                        PTCATALOG_ENTRY Entry)
+{
+    PPROTOCOL_ENUM_CONTEXT Context = (PPROTOCOL_ENUM_CONTEXT)EnumContext;
+    LPWSAPROTOCOL_INFOW ProtocolInfo = &Entry->ProtocolInfo;
+
+    /* Check if this protocol matches */
+    if (CheckProtocolMatch(Context->Protocols, ProtocolInfo))
+    {
+        /* Copy the information */
+        ProtocolInfoFromContext(ProtocolInfo, Context);
+        Context->BufferUsed += sizeof(*ProtocolInfo);
+    }
+
+    /* Continue enumeration */
+    return TRUE;
+}
+
+PTCATALOG
+WSAAPI
+OpenInitializedCatalog(VOID)
+{
+    INT ErrorCode;
+    PTCATALOG Catalog;
+    HKEY WsKey;
+
+    /* Allocate the catalog */
+    Catalog = WsTcAllocate();
+    if (Catalog)
+    {
+        /* Open the WS Key */
+        WsKey = WsOpenRegistryRoot();
+
+        /* Initialize the catalog */
+        ErrorCode = WsTcInitializeFromRegistry(Catalog, WsKey, NULL);
+
+        /* Close the key */
+        RegCloseKey(WsKey);
+    }
+
+    /* Return it */
+    return Catalog;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSPAPI
+WSCEnumProtocols(IN LPINT lpiProtocols,
+                 OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
+                 IN OUT LPDWORD lpdwBufferLength,
+                 OUT LPINT lpErrno)
+{
+    INT Status;
+    PTCATALOG Catalog;
+    PROTOCOL_ENUM_CONTEXT Context;
+    DPRINT("WSCEnumProtocols: %p\n", lpiProtocols);
+
+    /* Create a catalog object from the current one */
+    Catalog = OpenInitializedCatalog();
+    if (!Catalog)
+    {
+        /* Fail if we couldn't */
+        *lpErrno = WSAENOBUFS;
+        return SOCKET_ERROR;
+    }
+
+    /* Setup the context */
+    Context.Protocols = lpiProtocols;
+    Context.ProtocolBuffer = lpProtocolBuffer;
+    Context.BufferLength = lpProtocolBuffer ? *lpdwBufferLength : 0;
+    Context.BufferUsed = 0;
+    Context.Count = 0;
+    Context.ErrorCode = ERROR_SUCCESS;
+
+    /* Enumerate the catalog */
+    WsTcEnumerateCatalogItems(Catalog, ProtocolEnumerationProc, &Context);
+
+    /* Get status */
+    Status = Context.Count;
+
+    /* Check the error code */
+    if (Context.ErrorCode == ERROR_SUCCESS)
+    {
+        /* Check if enough space was available */
+        if (Context.BufferLength < Context.BufferUsed)
+        {
+            /* Fail and tell them how much we need */
+            *lpdwBufferLength = Context.BufferUsed;
+            *lpErrno = WSAENOBUFS;
+            Status = SOCKET_ERROR;
+        }
+    }
+    else
+    {
+        /* Failure, normalize error */
+        Status = SOCKET_ERROR;
+        *lpErrno = Context.ErrorCode;
+    }
+
+    /* Delete the catalog object */
+    WsTcDelete(Catalog);
+
+    /* Return */
+    return Status;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAEnumProtocolsA(IN LPINT lpiProtocols,
+                  OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer,
+                  IN OUT LPDWORD lpdwBufferLength)
+{
+    DPRINT("WSAEnumProtocolsA: %p\n", lpiProtocols);
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAEnumProtocolsW(IN LPINT lpiProtocols,
+                  OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
+                  IN OUT  LPDWORD lpdwBufferLength)
+{
+    DPRINT("WSAEnumProtocolsW: %p\n", lpiProtocols);
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUGetProviderPath(IN LPGUID lpProviderId,
+                   OUT LPWSTR lpszProviderDllPath,
+                   IN OUT LPINT lpProviderDllPathLen,
+                   OUT LPINT lpErrno)
+{
+    DPRINT("WPUGetProviderPath: %p\n", lpProviderId);
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle,
+                        IN LPWSAOVERLAPPED lpOverlapped,
+                        IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    DPRINT("WSAProviderConfigChange: %p\n", lpNotificationHandle);
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCGetProviderPath(IN LPGUID lpProviderId,
+                   OUT LPWSTR lpszProviderDllPath,
+                   IN OUT LPINT lpProviderDllPathLen,
+                   OUT LPINT lpErrno)
+{
+    DPRINT("WSCGetProviderPath: %p\n", lpProviderId);
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/event.c b/reactos/dll/win32/ws2_32_new/src/event.c
new file mode 100644 (file)
index 0000000..d24d5f8
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        event.c
+ * PURPOSE:     Socket Events
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+                   
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSACloseEvent(IN WSAEVENT hEvent)
+{
+    BOOL Success;
+
+    /* Let the OS handle it */
+    Success = CloseHandle(hEvent);
+
+    /* We need a special WSA return error */
+    if (!Success) WSASetLastError(WSA_INVALID_HANDLE);
+
+    /* Return the Win32 Error */
+    return Success;
+}
+
+/*
+ * @implemented
+ */
+WSAEVENT
+WSAAPI
+WSACreateEvent(VOID)
+{
+    /* CreateEventW can only return the Event or 0 (WSA_INVALID_EVENT) */
+    return CreateEventW(NULL, TRUE, FALSE, NULL);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSAResetEvent(IN WSAEVENT hEvent)
+{
+    /* Call Win32 */
+    return ResetEvent(hEvent);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSASetEvent(IN WSAEVENT hEvent)
+{
+    /* Call Win32 */
+    return SetEvent(hEvent);
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WSAAPI
+WSAWaitForMultipleEvents(IN DWORD cEvents,
+                         IN CONST WSAEVENT FAR* lphEvents,
+                         IN BOOL fWaitAll,
+                         IN DWORD dwTimeout,
+                         IN BOOL fAlertable)
+{
+    /* Call Win32 */
+    return WaitForMultipleObjectsEx(cEvents, 
+                                    lphEvents, 
+                                    fWaitAll, 
+                                    dwTimeout, 
+                                    fAlertable);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAEnumNetworkEvents(IN SOCKET s,
+                     IN WSAEVENT hEventObject,
+                     OUT LPWSANETWORKEVENTS lpNetworkEvents)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSAEnumNetworkEvents: %lx\n", s);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPEnumNetworkEvents(s,
+                                                              hEventObject,
+                                                              lpNetworkEvents,
+                                                              &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
diff --git a/reactos/dll/win32/ws2_32_new/src/getproto.c b/reactos/dll/win32/ws2_32_new/src/getproto.c
new file mode 100644 (file)
index 0000000..e4a06cc
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        getproto.c
+ * PURPOSE:     GetProtoByY Functions.
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+HANDLE
+WSAAPI
+GetProtoOpenNetworkDatabase(PCHAR Name)
+{
+    CHAR ExpandedPath[MAX_PATH];
+    CHAR DatabasePath[MAX_PATH];
+    INT ErrorCode;
+    HKEY DatabaseKey;
+    DWORD RegType;
+    DWORD RegSize = sizeof(DatabasePath);
+
+    /* Open the database path key */
+    ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                             "System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+                             0,
+                             KEY_READ,
+                             &DatabaseKey);
+    if (ErrorCode == NO_ERROR)
+    {
+        /* Read the actual path */
+        ErrorCode = RegQueryValueEx(DatabaseKey,
+                                    "DatabasePath",
+                                    NULL,
+                                    &RegType,
+                                    DatabasePath,
+                                    &RegSize);
+
+        /* Close the key */
+        RegCloseKey(DatabaseKey);
+
+        /* Expand the name */
+        ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
+    }
+    else
+    {
+        /* Use defalt path */
+        GetSystemDirectory(ExpandedPath, MAX_PATH);
+        strcat(ExpandedPath, "DRIVERS\\ETC\\");
+    }
+
+    /* Make sure that the path is backslash-terminated */
+    if (ExpandedPath[strlen(ExpandedPath) - 1] != '\\')
+    {
+        /* It isn't, so add it ourselves */
+        strcat(ExpandedPath, "\\");
+    }
+
+    /* Add the database name */
+    strcat(ExpandedPath, Name);
+
+    /* Return a handle to the file */
+    return CreateFile(ExpandedPath,
+                      FILE_READ_ACCESS,
+                      0,
+                      NULL,
+                      OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL,
+                      NULL); 
+}
+
+PCHAR
+WSAAPI
+GetProtoPatternMatch(IN PCHAR Buffer,
+                     IN PCHAR Lookup)
+{
+    CHAR ScanChar;
+
+    /* Loop as long as we have data */
+    while ((ScanChar = *Buffer))
+    {
+        /* Check for a match and return its pointer if found */
+        if (strchr(Lookup, ScanChar)) return Buffer;
+
+        /* Keep going */
+        Buffer++;
+    }
+
+    /* Nothing found */
+    return NULL;
+}
+
+PPROTOENT
+WSAAPI
+GetProtoGetNextEnt(IN HANDLE DbHandle,
+                   IN PWSPROTO_BUFFER Buffer)
+{
+    DWORD Read;
+    LONG n;
+    PCHAR p, p1, Entry, *Aliases;
+    PPROTOENT ReturnedProtoent;
+
+    /* Find out where we currently are in the file */
+    n = SetFilePointer(DbHandle, 0, 0, FILE_CURRENT);
+
+    while (TRUE)
+    {
+        /* Read 512 bytes */
+        if (!ReadFile(DbHandle,
+                      Buffer->LineBuffer,
+                      512,
+                      &Read,
+                      NULL)) return NULL;
+
+        /* Find out where the line ends */
+        p1 = Buffer->LineBuffer;
+        p = strchr(Buffer->LineBuffer, '\n');
+
+        /* Bail out if the file is parsed */
+        if (!p) return NULL;
+
+        /* Calculate our new position */
+        n += (LONG)(p - p1) + 1;
+
+        /* Make it so we read from there next time */
+        SetFilePointer(DbHandle, n, 0, FILE_BEGIN);
+
+        /* Null-terminate the buffer so it only contains this line */
+        *p = ANSI_NULL;
+
+        /* If this line is a comment, skip it */
+        if (*p1 == '#') continue;
+
+        /* Get the entry in this line and null-terminate it */
+        Entry = GetProtoPatternMatch(p1, "#\n");
+        if (!Entry) continue;
+        *Entry = ANSI_NULL;
+
+        /* Start with the name */
+        Buffer->Protoent.p_name = p1;
+
+        /* Get the first tab and null-terminate */
+        Entry = GetProtoPatternMatch(p1, " \t");
+        if (!Entry) continue;
+        *Entry++ = ANSI_NULL;
+
+        /* Handle remaining tabs or spaces */
+        while (*Entry == ' ' || *Entry == '\t') Entry++;
+
+        /* Now move our read pointer */
+        p1 = GetProtoPatternMatch(Entry, " \t");
+        if (p1) *p1++ = ANSI_NULL;
+
+        /* This is where the address is */
+        Buffer->Protoent.p_proto = (short)atoi(Entry);
+
+        /* Setup the alias buffer */
+        Buffer->Protoent.p_aliases = Buffer->Aliases;
+        Aliases = Buffer->Protoent.p_aliases;
+
+        /* Check if the pointer is stil valid */
+        if (p1)
+        {
+            /* The first entry is here */
+            Entry = p1;
+
+            /* Loop while there are non-null entries */
+            while (Entry && *Entry)
+            {
+                /* Handle tabs and spaces */
+                while (*Entry == ' ' || *Entry == '\t') Entry++;
+
+                /* Make sure we don't go over the buffer */
+                if (Aliases < &Buffer->Protoent.p_aliases[MAXALIASES - 1])
+                {
+                    /* Write the alias */
+                    *Aliases++ = Entry;
+                }
+
+                /* Get to the next entry */
+                Entry = GetProtoPatternMatch(Entry, " \t");
+                if (Entry) *Entry++ = ANSI_NULL;
+            }
+        }
+
+        /* Terminate the list */
+        *Aliases = NULL;
+
+        /* Return to caller */
+        ReturnedProtoent = &Buffer->Protoent;
+        break;
+    }
+
+    /* Return whatever we got */
+    return ReturnedProtoent;
+}
+
+/*
+ * @implemented
+ */
+LPPROTOENT
+WSAAPI
+getprotobynumber(IN INT number)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PPROTOENT Protoent;
+    PVOID GetProtoBuffer; 
+    HANDLE DbHandle;
+    DPRINT("getprotobynumber: %lx\n", number);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Get our buffer */
+    GetProtoBuffer = WsThreadGetProtoBuffer(Thread);
+    if (!GetProtoBuffer)
+    {
+        /* Fail */
+        SetLastError(WSANO_DATA);
+        return NULL;
+    }
+
+    /* Open the network database */
+    DbHandle = GetProtoOpenNetworkDatabase("protocol");
+    if (DbHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Couldn't open the DB; fail */
+        SetLastError(WSANO_DATA);
+        return NULL;
+    }
+
+    /* Start the scan loop */
+    while (TRUE)
+    {
+        /* Get a protoent entry */
+        Protoent = GetProtoGetNextEnt(DbHandle, GetProtoBuffer);
+
+        /* Break if we didn't get any new one */
+        if (!Protoent) break;
+
+        /* Break if we have a match */
+        if (Protoent->p_proto == number) break;
+    }
+
+    /* Close the network database */
+    CloseHandle(DbHandle);
+
+    /* Set error if we don't have a protoent */
+    if (!Protoent) SetLastError(WSANO_DATA);
+
+    /* Return it */
+    return Protoent;
+}
+
+/*
+ * @implemented
+ */
+LPPROTOENT
+WSAAPI
+getprotobyname(IN CONST CHAR FAR *name)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PPROTOENT Protoent;
+    PVOID GetProtoBuffer; 
+    HANDLE DbHandle;
+    DPRINT("getprotobyname: %s\n", name);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Get our buffer */
+    GetProtoBuffer = WsThreadGetProtoBuffer(Thread);
+    if (!GetProtoBuffer)
+    {
+        /* Fail */
+        SetLastError(WSANO_DATA);
+        return NULL;
+    }
+
+    /* Open the network database */
+    DbHandle = GetProtoOpenNetworkDatabase("protocol");
+    if (DbHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Couldn't open the DB; fail */
+        SetLastError(WSANO_DATA);
+        return NULL;
+    }
+
+    /* Start the scan loop */
+    while (TRUE)
+    {
+        /* Get a protoent entry */
+        Protoent = GetProtoGetNextEnt(DbHandle, GetProtoBuffer);
+
+        /* Break if we didn't get any new one */
+        if (!Protoent) break;
+
+        /* Break if we have a match */
+        if (!_stricmp(Protoent->p_name, name)) break;
+    }
+
+    /* Close the network database */
+    CloseHandle(DbHandle);
+
+    /* Set error if we don't have a protoent */
+    if (!Protoent) SetLastError(WSANO_DATA);
+
+    /* Return it */
+    return Protoent;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/getxbyxx.c b/reactos/dll/win32/ws2_32_new/src/getxbyxx.c
new file mode 100644 (file)
index 0000000..dd989e6
--- /dev/null
@@ -0,0 +1,958 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        getxbyy.c
+ * PURPOSE:     Get X by Y Functions for Name Resolution.
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+AFPROTOCOLS afp[2] = {{AF_INET, IPPROTO_UDP}, {AF_INET, IPPROTO_TCP}};
+                     
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WSAAPI
+FixList(PCHAR **List, 
+        ULONG_PTR Base)
+{
+    /* Make sure it's valid */
+    if(*List)
+    {
+        PCHAR *Addr;
+
+        /* Get the right base */
+        Addr = *List = (PCHAR*)(((ULONG_PTR)*List + Base));
+
+        /* Loop the pointers */
+        while(*Addr)
+        {
+            /* Rebase them too */
+            *Addr = (PCHAR)(((ULONG_PTR)*Addr + Base));
+            Addr++;
+        }
+    }
+}
+
+VOID
+WSAAPI
+UnpackServEnt(PSERVENT Servent)
+{
+    ULONG_PTR ServentPtr = (ULONG_PTR)Servent;
+
+    /* Convert all the List Offsets to Pointers */
+    FixList(&Servent->s_aliases, ServentPtr);
+
+    /* Convert the Name and Protocol Offesets to Pointers */
+    Servent->s_name = (PCHAR)(Servent->s_name + ServentPtr);
+    Servent->s_proto = (PCHAR)(Servent->s_proto + ServentPtr);
+}
+
+VOID
+WSAAPI
+UnpackHostEnt(PHOSTENT Hostent)
+{
+    ULONG_PTR HostentPtr = (ULONG_PTR)Hostent;
+
+    /* Convert the Name Offset to a Pointer */
+    if(Hostent->h_name) Hostent->h_name = (PCHAR)(Hostent->h_name + HostentPtr);
+
+    /* Convert all the List Offsets to Pointers */
+    FixList(&Hostent->h_aliases, HostentPtr);
+    FixList(&Hostent->h_addr_list, HostentPtr);
+}
+
+VOID
+WSAAPI
+Local_Ip4AddresstoString(IN PCHAR AddressBuffer,
+                         IN PCHAR Address)
+{
+    /* Convert the address into IPv4 format */
+    sprintf(AddressBuffer, "%u.%u.%u.%u",
+            ((unsigned)Address[0] & 0xff),
+            ((unsigned)Address[1] & 0xff),
+            ((unsigned)Address[2] & 0xff),
+            ((unsigned)Address[3] & 0xff));
+}
+
+VOID
+WSAAPI
+Local_Ip6AddresstoString(IN PCHAR AddressBuffer,
+                         IN PCHAR Address)
+{
+    DWORD i;
+
+    /* Convert the address into IPv6 format */
+    for (i = 0; i < 8; i++)
+    {
+        sprintf(AddressBuffer, "%x:",
+                ((unsigned)Address[0] & 0xff));
+    }
+}
+
+LPBLOB
+WSAAPI
+getxyDataEnt(IN OUT PCHAR *Results,
+             IN DWORD Length,
+             IN LPSTR Name,
+             IN LPGUID Type,
+             IN LPSTR *NewName)
+{
+    PWSAQUERYSETA WsaQuery = (PWSAQUERYSETA)*Results;
+    INT ErrorCode;
+    HANDLE RnRHandle;
+    LPBLOB Blob = NULL;
+    PVOID NewResults;
+
+    /* Assume empty return name */
+    if (NewName) *NewName = NULL;
+
+    /* Set up the Winsock Service Query */
+    RtlZeroMemory(WsaQuery, sizeof(*WsaQuery));
+    WsaQuery->dwSize = sizeof(*WsaQuery);
+    WsaQuery->lpszServiceInstanceName = Name;
+    WsaQuery->lpServiceClassId = Type;
+    WsaQuery->dwNameSpace = NS_ALL;
+    WsaQuery->dwNumberOfProtocols = 2;
+    WsaQuery->lpafpProtocols = &afp[0];
+
+    /* Send the Query Request to find a Service */
+    ErrorCode = WSALookupServiceBeginA(WsaQuery,
+                                       LUP_RETURN_BLOB | LUP_RETURN_NAME,
+                                       &RnRHandle);
+
+    if(ErrorCode == ERROR_SUCCESS) 
+    {
+        while (TRUE)
+        {
+            /* Service was found, send the real query */
+            ErrorCode = WSALookupServiceNextA(RnRHandle,
+                                              0,
+                                              &Length,
+                                              WsaQuery);
+
+            /* Return the information requested */
+            if(ErrorCode == ERROR_SUCCESS) 
+            {
+                /* Get the Blob and check if we have one */
+                Blob = WsaQuery->lpBlob;
+                if(Blob) 
+                {
+                    /* Did they want the name back? */
+                    if(NewName) *NewName = WsaQuery->lpszServiceInstanceName;
+                } 
+                else 
+                {
+                    /* Check if this was a Hostname lookup */
+                    if (Type == &HostnameGuid)
+                    {
+                        /* Return the name anyways */
+                        if(NewName) *NewName = WsaQuery->lpszServiceInstanceName;
+                    }
+                    else
+                    {
+                        /* We don't have a blob, sorry */
+                        ErrorCode = WSANO_DATA;
+                    }
+                }
+            } 
+            else 
+            {
+                /* WSALookupServiceEnd will set its own error, so save ours */
+                ErrorCode = GetLastError();
+
+                /* Check if we failed because of missing buffer space */
+                if ((ErrorCode == WSAEFAULT) && (Length > RNR_BUFFER_SIZE))
+                {
+                    /* Allocate a new buffer */
+                    NewResults = HeapAlloc(WsSockHeap, 0, Length);
+                    if (NewResults)
+                    {
+                        /* Tell the caller his new buffer */
+                        *Results = NewResults;
+
+                        /* Update the WSA Query's location */
+                        WsaQuery = (PWSAQUERYSETA)NewResults;
+
+                        /* Loop again */
+                        continue;
+                    }
+                    else
+                    {
+                        /* No memory to allocate the new buffer */
+                        ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+                    }
+                }
+            }
+        
+            /* Finish the Query Request */
+            WSALookupServiceEnd(RnRHandle);
+
+            /* Now set the Last Error */
+            if(ErrorCode != ERROR_SUCCESS) SetLastError(ErrorCode);
+
+            /* Leave the loop */
+            break;
+        }
+    }
+
+    /* Return the blob */
+    return Blob;
+}
+
+/*
+ * @implemented
+ */
+PHOSTENT
+WSAAPI
+gethostbyname(IN const char FAR * name)
+{
+    PHOSTENT Hostent;
+    LPBLOB Blob;
+    INT ErrorCode;
+    CHAR ResultsBuffer[RNR_BUFFER_SIZE];
+    PCHAR Results = ResultsBuffer;
+    CHAR szLocalName[200];
+    PCHAR pszName;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    DPRINT("gethostbyname: %s\n", name);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Check if no name was given */
+    if(!name || !*name) 
+    {
+        /* This means we should do a local lookup first */
+        if(gethostname(szLocalName, 200) != NO_ERROR) return(NULL);
+        pszName = szLocalName;
+    } 
+    else 
+    {
+        /* Use the name tha twas given to us */
+        pszName = (PCHAR)name;
+    }
+
+    /* Get the Hostname in a Blob Structure */
+    Blob = getxyDataEnt(&Results,
+                        RNR_BUFFER_SIZE,
+                        pszName,
+                        &HostAddrByNameGuid,
+                        0);
+    
+    /* Check if we didn't get a blob, or if we got an empty name */
+    if (!(Blob) && (!(name) || !(*name)))
+    {
+        /* Try a new query */
+        Blob = getxyDataEnt(&Results,
+                            RNR_BUFFER_SIZE,
+                            NULL,
+                            &HostAddrByNameGuid,
+                            0);
+    }
+
+    /* Check if we got a blob */
+    if(Blob) 
+    {
+        /* Copy the blob to our buffer and convert it */
+        Hostent = WsThreadBlobToHostent(Thread, Blob);
+
+        /* Unpack the hostent */
+        if(Hostent) UnpackHostEnt(Hostent);
+    } 
+    else 
+    {
+        /* We failed, so zero it out */
+        Hostent = 0;
+
+        /* Normalize the error message */
+        if(GetLastError() == WSASERVICE_NOT_FOUND) 
+        {
+            SetLastError(WSAHOST_NOT_FOUND);
+        }
+    }
+
+    /* Check if we received a newly allocated buffer; free it. */
+    if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
+
+    /* Notify RAS Auto-dial helper */
+    if (Hostent) WSNoteSuccessfulHostentLookup(name, *Hostent->h_addr);
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+/*
+ * @implemented
+ */
+PHOSTENT
+WSAAPI
+gethostbyaddr(IN const char FAR * addr,
+              IN int len,
+              IN int type)
+{
+    CHAR AddressBuffer[100];
+    PHOSTENT Hostent;
+    LPBLOB Blob;
+    CHAR ResultsBuffer[RNR_BUFFER_SIZE];
+    PCHAR Results = ResultsBuffer;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("gethostbyaddr: %s\n", addr);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Check for valid address pointer */
+    if (!addr)
+    {
+        /* Fail */
+        SetLastError(WSAEINVAL);
+        return NULL;
+    }
+
+    /* Check which type it is */
+    if (type == AF_INET)
+    {
+        /* Use IPV4 Address to String */
+        Local_Ip4AddresstoString(AddressBuffer, (PCHAR)addr);
+    }
+    else if (type == AF_INET6)
+    {
+        /* Use IPV6 Address to String */
+        Local_Ip6AddresstoString(AddressBuffer, (PCHAR)addr);
+    }
+    else
+    {
+        /* Invalid address type; fail */
+        SetLastError(WSAEINVAL);
+        return NULL;
+    }
+
+    /* Get the Hostname in a Blob Structure */
+    Blob = getxyDataEnt(&Results,
+                        RNR_BUFFER_SIZE,
+                        AddressBuffer,
+                        &AddressGuid,
+                        0);
+    
+    /* Check if we got a blob */
+    if(Blob) 
+    {
+        /* Copy the blob to our buffer and convert it */
+        Hostent = WsThreadBlobToHostent(Thread, Blob);
+
+        /* Unpack the hostent */
+        if(Hostent) UnpackHostEnt(Hostent);
+    } 
+    else 
+    {
+        /* We failed, so zero it out */
+        Hostent = 0;
+
+        /* Normalize the error message */
+        if(GetLastError() == WSASERVICE_NOT_FOUND) 
+        {
+            SetLastError(WSAHOST_NOT_FOUND);
+        }
+    }
+
+    /* Check if we received a newly allocated buffer; free it. */
+    if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+gethostname(OUT char FAR * name,
+            IN int namelen)
+{
+    PCHAR Name;
+    CHAR ResultsBuffer[RNR_BUFFER_SIZE];
+    PCHAR Results = ResultsBuffer;
+    DPRINT("gethostname: %p\n", name);
+
+    /* Get the Hostname in a String */
+    if(getxyDataEnt(&Results, RNR_BUFFER_SIZE, NULL, &HostnameGuid, &Name))
+    {
+        /* Copy it */
+        strcpy((LPSTR)name, Name);
+    }
+
+    /* Check if we received a newly allocated buffer; free it. */
+    if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+PSERVENT
+WSAAPI
+getservbyport(IN int port,
+              IN const char FAR * proto)
+{
+    PSERVENT Servent;
+    LPBLOB Blob;
+    CHAR ResultsBuffer[RNR_BUFFER_SIZE];
+    PCHAR Results = ResultsBuffer;
+    PCHAR PortName;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("getservbyport: %s\n", proto);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* No protocol specifed */
+    if(!proto) proto = "";
+
+    /* Allocate memory for the port name */
+    PortName = HeapAlloc(WsSockHeap, 0, strlen(proto) + 1 + 1 + 5);
+    if (!PortName)
+    {
+        /* Fail */
+        SetLastError(WSA_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    /* Put it into the right syntax */
+    sprintf(PortName, "%d/%s", (port & 0xffff), proto);
+
+    /* Get the Service in a Blob */
+    Blob = getxyDataEnt(&Results, RNR_BUFFER_SIZE, PortName, &IANAGuid, 0);
+
+    /* Free the string we sent */
+    HeapFree(WsSockHeap, 0, PortName);
+
+    /* Check if we got a blob */
+    if(Blob) 
+    {
+        /* Copy the blob to our buffer and convert it */
+        Servent = WsThreadBlobToServent(Thread, Blob);
+
+        /* Unpack the hostent */
+        if(Servent) UnpackServEnt(Servent);
+    } 
+    else 
+    {
+        /* We failed, so zero it out */
+        Servent = 0;
+
+        /* Normalize the error message */
+        if(GetLastError() == WSATYPE_NOT_FOUND) SetLastError(WSANO_DATA);
+    }
+
+    /* Check if we received a newly allocated buffer; free it. */
+    if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
+
+    /* Return the hostent */
+    return Servent;
+}
+
+/*
+ * @implemented
+ */
+PSERVENT
+WSAAPI
+getservbyname(IN const char FAR * name,
+              IN const char FAR * proto)
+{
+    PSERVENT Servent;
+    LPBLOB Blob;
+    CHAR ResultsBuffer[RNR_BUFFER_SIZE];
+    PCHAR Results = ResultsBuffer;
+    PCHAR PortName;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("getservbyname: %s\n", name);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* No protocol specifed */
+    if(!proto) proto = "";
+
+    /* Allocate buffer for it */
+    PortName = HeapAlloc(WsSockHeap, 0, strlen(proto) + 1 + strlen(name) + 1);
+    if (!PortName)
+    {
+        /* Fail */
+        SetLastError(WSA_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    /* Put it into the right syntax */
+    sprintf(PortName, "%s/%s", name, proto);
+
+    /* Get the Service in a Blob */
+    Blob = getxyDataEnt(&Results, RNR_BUFFER_SIZE, PortName, &IANAGuid, 0);
+
+    /* Free the string we sent */
+    HeapFree(WsSockHeap, 0, PortName);
+
+    /* Check if we got a blob */
+    if(Blob) 
+    {
+        /* Copy the blob to our buffer and convert it */
+        Servent = WsThreadBlobToServent(Thread, Blob);
+
+        /* Unpack the hostent */
+        if(Servent) UnpackServEnt(Servent);
+    } 
+    else 
+    {
+        /* We failed, so zero it out */
+        Servent = 0;
+
+        /* Normalize the error message */
+        if(GetLastError() == WSATYPE_NOT_FOUND) SetLastError(WSANO_DATA);
+    }
+
+    /* Check if we received a newly allocated buffer; free it. */
+    if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
+
+    /* Return the hostent */
+    return Servent;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetHostByAddr(IN HWND hWnd,
+                      IN UINT wMsg,
+                      IN CONST CHAR FAR *Address, 
+                      IN INT Length,
+                      IN INT Type, 
+                      OUT CHAR FAR *Buffer, 
+                      IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PVOID AddressCopy;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    DPRINT("WSAAsyncGetHostByAddr: %lx, %lx, %s\n", hWnd, wMsg, Address);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(Length)))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Make a copy of the address */
+    AddressCopy = AsyncBlock + 1;
+    RtlMoveMemory(AddressCopy, Address, Length);
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetHostByAddr;
+    AsyncBlock->GetHost.hWnd = hWnd;
+    AsyncBlock->GetHost.wMsg = wMsg;
+    AsyncBlock->GetHost.ByWhat = AddressCopy;
+    AsyncBlock->GetHost.Length = Length;
+    AsyncBlock->GetHost.Type = Type;
+    AsyncBlock->GetHost.Buffer = Buffer;
+    AsyncBlock->GetHost.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetHostByName(IN HWND hWnd, 
+                      IN UINT wMsg,  
+                      IN CONST CHAR FAR *Name, 
+                      OUT CHAR FAR *Buffer, 
+                      IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    PVOID NameCopy;
+    DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd, wMsg, Name);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Make a copy of the address */
+    NameCopy = AsyncBlock + 1;
+    strcpy(NameCopy, Name);
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetHostByName;
+    AsyncBlock->GetHost.hWnd = hWnd;
+    AsyncBlock->GetHost.wMsg = wMsg;
+    AsyncBlock->GetHost.ByWhat = NameCopy;
+    AsyncBlock->GetHost.Buffer = Buffer;
+    AsyncBlock->GetHost.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetProtoByName(IN HWND hWnd,
+                       IN UINT wMsg,
+                       IN CONST CHAR FAR *Name,
+                       OUT CHAR FAR *Buffer,
+                       IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    PVOID NameCopy;
+    DPRINT("WSAAsyncGetProtoByName: %lx, %lx, %s\n", hWnd, wMsg, Name);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Make a copy of the address */
+    NameCopy = AsyncBlock + 1;
+    strcpy(NameCopy, Name);
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetProtoByName;
+    AsyncBlock->GetProto.hWnd = hWnd;
+    AsyncBlock->GetProto.wMsg = wMsg;
+    AsyncBlock->GetProto.ByWhat = NameCopy;
+    AsyncBlock->GetProto.Buffer = Buffer;
+    AsyncBlock->GetProto.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetProtoByNumber(IN HWND hWnd,
+                         IN UINT wMsg,
+                         IN INT Number,
+                         OUT CHAR FAR* Buffer,
+                         IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd, wMsg, Number);
+    
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(0)))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetProtoByNumber;
+    AsyncBlock->GetProto.hWnd = hWnd;
+    AsyncBlock->GetProto.wMsg = wMsg;
+    AsyncBlock->GetProto.ByWhat = UlongToPtr(Number);
+    AsyncBlock->GetProto.Buffer = Buffer;
+    AsyncBlock->GetProto.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetServByName(IN HWND hWnd,
+                      IN UINT wMsg,
+                      IN CONST CHAR FAR *Name,
+                      IN CONST CHAR FAR *Protocol,
+                      OUT CHAR FAR *Buffer,
+                      IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    PVOID NameCopy;
+    DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd, wMsg, Name);
+    
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Make a copy of the address */
+    NameCopy = AsyncBlock + 1;
+    strcpy(NameCopy, Name);
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetProtoByName;
+    AsyncBlock->GetServ.hWnd = hWnd;
+    AsyncBlock->GetServ.wMsg = wMsg;
+    AsyncBlock->GetServ.ByWhat = NameCopy;
+    AsyncBlock->GetServ.Protocol = (PCHAR)Protocol;
+    AsyncBlock->GetServ.Buffer = Buffer;
+    AsyncBlock->GetServ.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+WSAAPI
+WSAAsyncGetServByPort(IN HWND hWnd,
+                      IN UINT wMsg,
+                      IN INT Port,
+                      IN CONST CHAR FAR *Protocol,
+                      OUT CHAR FAR *Buffer,
+                      IN INT BufferLength)
+{
+    HANDLE TaskHandle;
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSASYNCBLOCK AsyncBlock;
+    INT ErrorCode;
+    DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd, wMsg, Port);
+    
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return NULL;
+    }
+
+    /* Initialize the Async Thread */
+    if (!WsAsyncCheckAndInitThread())
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Allocate an async block */
+    if (!(AsyncBlock = WsAsyncAllocateBlock(0)))
+    {
+        /* Fail */
+        SetLastError(WSAENOBUFS);
+        return NULL;
+    }
+
+    /* Initialize the Async Block */
+    AsyncBlock->Operation = WsAsyncGetServByPort;
+    AsyncBlock->GetServ.hWnd = hWnd;
+    AsyncBlock->GetServ.wMsg = wMsg;
+    AsyncBlock->GetServ.ByWhat = UlongToPtr(Port);
+    AsyncBlock->GetServ.Protocol = (PCHAR)Protocol;
+    AsyncBlock->GetServ.Buffer = Buffer;
+    AsyncBlock->GetServ.BufferLength = BufferLength;
+
+    /* Save the task handle and queue the request */
+    TaskHandle = AsyncBlock->TaskHandle;
+    WsAsyncQueueRequest(AsyncBlock);
+
+    /* Return the task handle */
+    return TaskHandle;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    DPRINT("WSACancelAsyncRequest: %lx\n", hAsyncTaskHandle);
+    
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Call the Async code */
+        ErrorCode = WsAsyncCancelRequest(hAsyncTaskHandle);
+
+        /* Return */
+        if (ErrorCode == ERROR_SUCCESS) return ERROR_SUCCESS;
+    }
+    
+    /* Fail */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/ioctl.c b/reactos/dll/win32/ws2_32_new/src/ioctl.c
new file mode 100644 (file)
index 0000000..09c4bdb
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        ioctl.c
+ * PURPOSE:     Socket I/O Control Code support.
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+ioctlsocket(IN SOCKET s,
+            IN LONG cmd,
+            IN OUT ULONG FAR* argp)
+{
+    DWORD Dummy;
+
+    /* Let WSA do it */
+    return WSAIoctl(s,
+                    cmd,
+                    argp,
+                    sizeof(ULONG),
+                    argp,
+                    sizeof(ULONG),
+                    &Dummy,
+                    NULL,
+                    NULL);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAIoctl(IN SOCKET s,
+         IN DWORD dwIoControlCode,
+         IN LPVOID lpvInBuffer,
+         IN DWORD cbInBuffer,
+         OUT LPVOID lpvOutBuffer,
+         IN DWORD cbOutBuffer,
+         OUT LPDWORD lpcbBytesReturned,
+         IN LPWSAOVERLAPPED lpOverlapped,
+         IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    DPRINT("WSAIoctl: %lx, %lx\n", s, dwIoControlCode);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPIoctl(s,
+                                                  dwIoControlCode,
+                                                  lpvInBuffer,
+                                                  cbInBuffer,
+                                                  lpvOutBuffer,
+                                                  cbOutBuffer,
+                                                  lpcbBytesReturned,
+                                                  lpOverlapped,
+                                                  lpCompletionRoutine,
+                                                  ThreadId,
+                                                  &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/nscatalo.c b/reactos/dll/win32/ws2_32_new/src/nscatalo.c
new file mode 100644 (file)
index 0000000..2511b41
--- /dev/null
@@ -0,0 +1,619 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        nscatalo.c
+ * PURPOSE:     Namespace Catalog Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+#define NSCATALOG_NAME      "NameSpace_Catalog5"
+#define WsNcLock()          EnterCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+#define WsNcUnlock()        LeaveCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+
+/* FUNCTIONS *****************************************************************/
+
+PNSCATALOG
+WSAAPI
+WsNcAllocate(VOID)
+{
+    PNSCATALOG Catalog;
+
+    /* Allocate the catalog */
+    Catalog = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Catalog));
+
+    /* Return it */
+    return Catalog;
+}
+
+BOOLEAN
+WSAAPI
+WsNcOpen(IN PNSCATALOG Catalog,
+         IN HKEY ParentKey)
+{
+    LONG ErrorCode;
+    DWORD CreateDisposition;
+    HKEY CatalogKey, NewKey;
+    //DWORD CatalogEntries = 0;
+    DWORD RegType = REG_DWORD;
+    DWORD RegSize = sizeof(DWORD);
+    DWORD UniqueId = 0;
+    DWORD NewData = 0;
+
+    /* Initialize the catalog lock and namespace list */
+    InitializeCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+    InitializeListHead(&Catalog->CatalogList);
+
+    /* Open the Catalog Key */
+    ErrorCode = RegOpenKeyEx(ParentKey,
+                             NSCATALOG_NAME,
+                             0,
+                             MAXIMUM_ALLOWED,
+                             &CatalogKey);
+
+    /* If we didn't find the key, create it */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Fake that we opened an existing key */
+        CreateDisposition = REG_OPENED_EXISTING_KEY;
+    }
+    else if (ErrorCode == ERROR_FILE_NOT_FOUND)
+    {
+        /* Create the Catalog Name */
+        ErrorCode = RegCreateKeyEx(ParentKey,
+                                   NSCATALOG_NAME,
+                                   0,
+                                   NULL,
+                                   REG_OPTION_NON_VOLATILE,
+                                   KEY_ALL_ACCESS,
+                                   NULL,
+                                   &CatalogKey,
+                                   &CreateDisposition);
+    }
+
+    /* Fail if that didn't work */
+    if (ErrorCode != ERROR_SUCCESS) return FALSE;
+
+    /* Check if we had to create the key */
+    if (CreateDisposition == REG_CREATED_NEW_KEY)
+    {
+        /* Write the count of entries (0 now) */
+        ErrorCode = RegSetValueEx(CatalogKey,
+                                  "Num_Catalog_Entries",
+                                  0,
+                                  REG_DWORD,
+                                  (LPBYTE)&NewData,
+                                  sizeof(NewData));
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Write the first catalog entry Uniqe ID */
+        NewData = 1;
+        ErrorCode = RegSetValueEx(CatalogKey,
+                                  "Serial_Access_Num",
+                                  0,
+                                  REG_DWORD,
+                                  (LPBYTE)&NewData,
+                                  sizeof(NewData));
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Create a key for this entry */
+        ErrorCode = RegCreateKeyEx(CatalogKey,
+                                   "Catalog_Entries",
+                                   0,
+                                   NULL,
+                                   REG_OPTION_NON_VOLATILE,
+                                   KEY_ALL_ACCESS,
+                                   NULL,
+                                   &NewKey,
+                                   &CreateDisposition);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Close the key and fail */
+            RegCloseKey(CatalogKey);
+            return FALSE;
+        }
+
+        /* Close the key since we don't need it */
+        RegCloseKey(NewKey);
+    }
+    else
+    {
+        /* Read the serial number */
+        ErrorCode = RegQueryValueEx(CatalogKey,
+                                    "Serial_Access_Num",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&UniqueId,
+                                    &RegSize);
+
+        /* Check if it's missing for some reason */
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Write the first catalog entry Unique ID */
+            NewData = 1;
+            ErrorCode = RegSetValueEx(CatalogKey,
+                                      "Serial_Access_Num",
+                                      0,
+                                      REG_DWORD,
+                                      (LPBYTE)&NewData,
+                                      sizeof(NewData));
+        }
+    }
+
+    /* Set the Catalog Key */
+    Catalog->CatalogKey = CatalogKey;
+    return TRUE;
+}
+
+INT
+WSAAPI
+WsNcInitializeFromRegistry(IN PNSCATALOG Catalog,
+                           IN HKEY ParentKey,
+                           IN HANDLE CatalogEvent)
+{
+    INT ErrorCode = WSASYSCALLFAILURE;
+
+    /* Open the catalog */
+    if (WsNcOpen(Catalog, ParentKey))
+    {
+        /* Refresh it */
+        ErrorCode = WsNcRefreshFromRegistry(Catalog, CatalogEvent);
+    }
+
+    /* Return the status */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WsNcRefreshFromRegistry(IN PNSCATALOG Catalog,
+                        IN HANDLE CatalogEvent)
+{
+    INT ErrorCode;
+    BOOLEAN LocalEvent = FALSE;
+    LIST_ENTRY LocalList;
+    DWORD UniqueId;
+    HKEY EntriesKey;
+    DWORD CatalogEntries;
+    PNSCATALOG_ENTRY CatalogEntry;
+    BOOL NewChangesMade;
+    PLIST_ENTRY Entry;
+    DWORD RegType = REG_DWORD;
+    DWORD RegSize = sizeof(DWORD);
+    DWORD i;
+
+    /* Check if we got an event */
+    if (!CatalogEvent)
+    {
+        /* Create an event ourselves */
+        CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!CatalogEvent) return WSASYSCALLFAILURE;
+        LocalEvent = TRUE;
+    }
+
+    /* Lock the catalog */
+    WsNcLock();
+
+    /* Initialize our local list for the loop */
+    InitializeListHead(&LocalList);
+
+    /* Start looping */
+    do
+    {
+        /* Setup notifications for the catalog entry */
+        ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey,
+                                             CatalogEvent,
+                                             &UniqueId);
+        if (ErrorCode != ERROR_SUCCESS) break;
+
+        /* Check if we've changed till now */
+        if (UniqueId == Catalog->UniqueId)
+        {
+            /* We haven't, so return */
+            ErrorCode = ERROR_SUCCESS;
+            break;
+        }
+
+        /* Now Open the Entries */
+        ErrorCode = RegOpenKeyEx(Catalog->CatalogKey,
+                                 "Catalog_Entries",
+                                 0,
+                                 MAXIMUM_ALLOWED,
+                                 &EntriesKey);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Find out how many there are */
+        ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
+                                    "Num_Catalog_Entries",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&CatalogEntries,
+                                    &RegSize);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Initialize them all */
+        for (i = 1; i <= CatalogEntries; i++) 
+        {
+            /* Allocate a Catalog Entry Structure */
+            CatalogEntry = WsNcEntryAllocate();
+            if (!CatalogEntry)
+            {
+                /* Not enough memory, fail */
+                ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+                break;
+            }
+
+            /* Initialize it from the Registry Key */
+            ErrorCode = WsNcEntryInitializeFromRegistry(CatalogEntry,
+                                                        EntriesKey,
+                                                        i);
+            if (ErrorCode != ERROR_SUCCESS)
+            {
+                /* We failed to get it, dereference the entry and leave */
+                WsNcEntryDereference(CatalogEntry);
+                break;
+            }
+
+            /* Insert it to our List */
+            InsertTailList(&LocalList, &CatalogEntry->CatalogLink);
+        }
+
+        /* Close the catalog key */
+        RegCloseKey(EntriesKey);
+
+        /* Check if we changed during our read and if we have success */
+        NewChangesMade = WsCheckCatalogState(CatalogEvent);
+        if (!NewChangesMade && ErrorCode == ERROR_SUCCESS)
+        {
+            /* All is good, update the protocol list */
+            WsNcUpdateNamespaceList(Catalog, &LocalList);
+
+            /* Update and return */
+            Catalog->UniqueId = UniqueId;
+            break;
+        }
+
+        /* We failed and/or catalog data changed, free what we did till now */
+        while (!IsListEmpty(&LocalList))
+        {
+            /* Get the LP Catalog Item */
+            Entry = RemoveHeadList(&LocalList);
+            CatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+
+            /* Dereference it */
+            WsNcEntryDereference(CatalogEntry);
+        }
+    } while (NewChangesMade);
+
+    /* Release the lock */
+    WsNcUnlock();
+
+    /* Close the event, if any was created by us */
+    if (LocalEvent) CloseHandle(CatalogEvent);
+
+    /* All Done */
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog,
+                          IN PNSCATALOG_ENUMERATE_PROC Callback,
+                          IN PVOID Context)
+{
+    PLIST_ENTRY Entry;
+    PNSCATALOG_ENTRY CatalogEntry;
+    BOOL GoOn = TRUE;
+
+    /* Lock the catalog */
+    WsNcLock();
+
+    /* Loop the entries */
+    Entry = Catalog->CatalogList.Flink;
+    while (GoOn && (Entry != &Catalog->CatalogList))
+    {
+        /* Get the entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+
+        /* Move to the next one and call the callback */
+        Entry = Entry->Flink;
+        GoOn = Callback(Context, CatalogEntry);
+    }
+
+    /* Release lock */
+    WsNcUnlock();
+}
+
+INT
+WSAAPI
+WsNcLoadProvider(IN PNSCATALOG Catalog,
+                 IN PNSCATALOG_ENTRY CatalogEntry)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    PNS_PROVIDER Provider;
+
+    /* Lock the catalog */
+    WsNcLock();
+
+    /* Check if we have a provider already */
+    if (!CatalogEntry->Provider)
+    {
+        /* Allocate a provider */
+        if ((Provider = WsNpAllocate()))
+        {
+            /* Initialize it */
+            ErrorCode = WsNpInitialize(Provider,
+                                       CatalogEntry->DllPath,
+                                       &CatalogEntry->ProviderId);
+
+                /* Ensure success */
+                if (ErrorCode == ERROR_SUCCESS)
+                {
+                    /* Set the provider */
+                    WsNcEntrySetProvider(CatalogEntry, Provider);
+                }
+
+            /* Dereference it */
+            WsNpDereference(Provider);
+        }
+        else
+        {
+            /* No memory */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+        }
+    }
+
+    /* Release the lock */
+    WsNcUnlock();
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WsNcGetServiceClassInfo(IN PNSCATALOG Catalog,
+                        IN OUT LPDWORD BugSize,
+                        IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+    /* Not yet implemented in the spec? */
+    SetLastError(ERROR_SUCCESS);
+    return SOCKET_ERROR;
+}
+
+VOID
+WSAAPI
+WsNcUpdateNamespaceList(IN PNSCATALOG Catalog,
+                        IN PLIST_ENTRY List)
+{
+    LIST_ENTRY TempList;
+    PNSCATALOG_ENTRY CatalogEntry, OldCatalogEntry;
+    PLIST_ENTRY Entry;
+
+    /* First move from our list to the old one */
+    InsertHeadList(&Catalog->CatalogList, &TempList);
+    RemoveEntryList(&Catalog->CatalogList);
+    InitializeListHead(&Catalog->CatalogList);
+
+    /* Loop every item on the list */
+    while (!IsListEmpty(List))
+    {
+        /* Get the catalog entry */
+        Entry = RemoveHeadList(List);
+        CatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+
+        /* Check if this item is already on our list */
+        Entry = TempList.Flink;
+        while (Entry != &TempList)
+        {
+            /* Get the catalog entry */
+            OldCatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+            Entry = Entry->Flink;
+
+            /* Check if they match */
+            if (memcmp(&CatalogEntry->ProviderId,
+                       &OldCatalogEntry->ProviderId,
+                       sizeof(GUID)))
+            {
+                /* We have a match, use the old item instead */
+                WsNcEntryDereference(CatalogEntry);
+                CatalogEntry = OldCatalogEntry;
+                RemoveEntryList(&CatalogEntry->CatalogLink);
+
+                /* Decrease the number of protocols we have */
+                Catalog->ItemCount--;
+                break;
+            }
+        }
+
+        /* Add this item */
+        InsertTailList(&Catalog->CatalogList, &CatalogEntry->CatalogLink);
+        Catalog->ItemCount++;
+    }
+
+    /* If there's anything left on the temporary list */
+    while (!IsListEmpty(&TempList))
+    {
+        /* Get the entry */
+        Entry = RemoveHeadList(&TempList);
+        CatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+
+        /* Remove it */
+        Catalog->ItemCount--;
+        WsNcEntryDereference(CatalogEntry);
+    }
+}
+
+INT
+WSAAPI
+WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog,
+                             IN LPGUID ProviderId,
+                             OUT PNSCATALOG_ENTRY *CatalogEntry)
+{
+    PLIST_ENTRY NextEntry = Catalog->CatalogList.Flink;
+    PNSCATALOG_ENTRY Entry;
+
+    /* Lock the catalog */
+    WsNcLock();
+
+    /* Match the Id with all the entries in the List */
+    while (NextEntry != &Catalog->CatalogList)
+    {
+        /* Get the Current Entry */
+        Entry = CONTAINING_RECORD(NextEntry, NSCATALOG_ENTRY, CatalogLink);
+        NextEntry = NextEntry->Flink;
+
+        /* Check if this is the Catalog Entry ID we want */
+        if (!(memcmp(&Entry->ProviderId, ProviderId, sizeof(GUID))))
+        {
+            /* Check if it doesn't already have a provider */
+            if (!Entry->Provider)
+            {
+                /* Match, load the Provider */
+                WsNcLoadProvider(Catalog, Entry);
+            }
+
+            /* Reference the entry and return it */
+            InterlockedIncrement(&Entry->RefCount);
+            *CatalogEntry = Entry;
+            break;
+        }
+    }
+
+    /* Release the catalog */
+    WsNcUnlock();
+
+    /* Return */
+    return ERROR_SUCCESS;
+}
+
+BOOL
+WSAAPI
+WsNcMatchProtocols(IN DWORD NameSpace,
+                   IN LONG AddressFamily,
+                   IN LPWSAQUERYSETW QuerySet)
+{
+    DWORD ProtocolCount = QuerySet->dwNumberOfProtocols;
+    LPAFPROTOCOLS AfpProtocols = QuerySet->lpafpProtocols;
+    LONG Family;
+
+    /* Check for valid family */
+    if (AddressFamily != -1)
+    {
+        /* Check if it's the magic */
+        if (AddressFamily == AF_UNSPEC) return TRUE;
+        Family = AddressFamily;
+    }
+    else
+    {
+        /* No family given, check for namespace */
+        if (NameSpace == NS_SAP)
+        {
+            /* Use IPX family */
+            Family = AF_IPX;
+        }
+        else
+        {
+            /* Other namespace, it's valid */
+            return TRUE;
+        }
+    }
+
+    /* Now try to get a match */
+    while (ProtocolCount--)
+    {
+        /* Check this protocol entry */
+        if ((AfpProtocols->iAddressFamily == AF_UNSPEC) ||
+            (AfpProtocols->iAddressFamily == Family))
+        {
+            /* Match found */
+            return TRUE;
+        }
+
+        /* Move to the next one */
+        AfpProtocols++;
+    }
+
+    /* No match */
+    return FALSE;
+}
+
+VOID
+WSAAPI
+WsNcRemoveCatalogItem(IN PNSCATALOG Catalog,
+                      IN PNSCATALOG_ENTRY Entry)
+{
+    /* Remove the entry from the list */
+    RemoveEntryList(&Entry->CatalogLink);
+
+    /* Decrease our count */
+    Catalog->ItemCount--;
+}
+
+VOID
+WSAAPI
+WsNcDelete(IN PNSCATALOG Catalog)
+{
+    PLIST_ENTRY Entry;
+    PNSCATALOG_ENTRY CatalogEntry;
+
+    /* Check if we're initialized */
+    if (!Catalog->CatalogList.Flink) return;
+
+    /* Acquire lock */
+    WsNcLock();
+
+    /* Loop every entry */
+    Entry = Catalog->CatalogList.Flink;
+    while (Entry != &Catalog->CatalogList)
+    {
+        /* Get this entry */
+        CatalogEntry = CONTAINING_RECORD(Entry, NSCATALOG_ENTRY, CatalogLink);
+
+        /* Remove it */
+        WsNcRemoveCatalogItem(Catalog, CatalogEntry);
+
+        /* Dereference it */
+        WsNcEntryDereference(CatalogEntry);
+
+        /* Move to the next entry */
+        Entry = Catalog->CatalogList.Flink;
+    }
+
+    /* Check if the catalog key is opened */
+    if (Catalog->CatalogKey)
+    {
+        /* Close it */
+        RegCloseKey(Catalog->CatalogKey);
+        Catalog->CatalogKey = NULL;
+    }
+
+    /* Release and delete the lock */
+    WsNcUnlock();
+    DeleteCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
+
+    /* Delete the object */
+    HeapFree(WsSockHeap, 0, Catalog);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/nscatent.c b/reactos/dll/win32/ws2_32_new/src/nscatent.c
new file mode 100644 (file)
index 0000000..190f774
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        nscatent.c
+ * PURPOSE:     Namespace Catalog Entry Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PNSCATALOG_ENTRY
+WSAAPI
+WsNcEntryAllocate(VOID)
+{
+    PNSCATALOG_ENTRY CatalogEntry;
+
+    /* Allocate the catalog */
+    CatalogEntry = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*CatalogEntry));
+
+    /* Set the default non-null members */
+    CatalogEntry->RefCount = 1;
+    CatalogEntry->Enabled = TRUE;
+    CatalogEntry->AddressFamily = -1;
+
+    /* Return it */
+    return CatalogEntry;
+}
+
+VOID
+WSAAPI
+WsNcEntryDelete(IN PNSCATALOG_ENTRY CatalogEntry)
+{
+    /* Check if a provider is loaded */
+    if (CatalogEntry->Provider)
+    {
+        /* Dereference it too */
+        WsNpDereference(CatalogEntry->Provider);
+        CatalogEntry->Provider = NULL;
+    }
+
+    /* Delete us */
+    HeapFree(WsSockHeap, 0, CatalogEntry);
+}
+
+VOID
+WSAAPI
+WsNcEntryDereference(IN PNSCATALOG_ENTRY CatalogEntry)
+{
+    /* Dereference and check if it's now 0 */
+    if (!(InterlockedDecrement(&CatalogEntry->RefCount)))
+    {
+        /* We can delete the Provider now */
+        WsNcEntryDelete(CatalogEntry);
+    }
+}
+
+INT
+WSAAPI
+WsNcEntryInitializeFromRegistry(IN PNSCATALOG_ENTRY CatalogEntry,
+                                IN HKEY ParentKey,
+                                IN ULONG UniqueId)
+{
+    CHAR CatalogEntryName[13];
+    HKEY EntryKey;
+    LONG Return;
+    ULONG RegType = REG_SZ;
+    ULONG RegSize = MAX_PATH;
+
+    /* Convert to a 00000xxx string */
+    sprintf(CatalogEntryName, "%0""12""i", UniqueId);
+
+    /* Open the Entry */
+    Return = RegOpenKeyEx(ParentKey,
+                          CatalogEntryName,
+                          0,
+                          KEY_READ,
+                          &EntryKey);
+
+    /* Read the Library Path */
+    Return = RegQueryValueExW(EntryKey,
+                              L"LibraryPath",
+                              0,
+                              &RegType,
+                              (LPBYTE)&CatalogEntry->DllPath,
+                              &RegSize);
+
+    /* Query Display String Size*/
+    Return = RegQueryValueExW(EntryKey,
+                              L"DisplayString",
+                              0,
+                              NULL,
+                              NULL,
+                              &RegSize);
+
+    /* Allocate it */
+    CatalogEntry->ProviderName = (LPWSTR)HeapAlloc(WsSockHeap, 0, RegSize);
+
+    /* Read it */
+    Return = RegQueryValueExW(EntryKey,
+                              L"DisplayString",
+                              0,
+                              &RegType,
+                              (LPBYTE)CatalogEntry->ProviderName,
+                              &RegSize);
+
+    /* Read the Provider Id */
+    RegType = REG_BINARY;
+    RegSize = sizeof(GUID);
+    Return = RegQueryValueEx(EntryKey,
+                             "ProviderId",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->ProviderId,
+                             &RegSize);
+
+    /* Read the Address Family */
+    RegType = REG_DWORD;
+    RegSize = sizeof(DWORD);
+    Return = RegQueryValueEx(EntryKey,
+                             "AddressFamily",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->AddressFamily,
+                             &RegSize);
+
+    /* Read the Namespace Id */
+    Return = RegQueryValueEx(EntryKey,
+                             "SupportedNamespace",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->NamespaceId,
+                             &RegSize);
+
+    /* Read the Enabled Flag */
+    Return = RegQueryValueEx(EntryKey,
+                             "Enabled",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->Enabled,
+                             &RegSize);
+
+    /* Read the Version */
+    Return = RegQueryValueEx(EntryKey,
+                             "Version",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->Version,
+                             &RegSize);
+
+    /* Read the Support Service Class Info Flag */
+    Return = RegQueryValueEx(EntryKey,
+                             "Version",
+                             0,
+                             &RegType,
+                             (LPBYTE)&CatalogEntry->StoresServiceClassInfo,
+                             &RegSize);
+
+    /* Done */
+    RegCloseKey(EntryKey);
+    return ERROR_SUCCESS;
+}
+
+VOID
+WSAAPI
+WsNcEntrySetProvider(IN PNSCATALOG_ENTRY Entry,
+                     IN PNS_PROVIDER Provider)
+{
+    /* Reference the provider */
+    InterlockedIncrement(&Provider->RefCount);
+
+    /* Set it */
+    Entry->Provider = Provider;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/nspinstl.c b/reactos/dll/win32/ws2_32_new/src/nspinstl.c
new file mode 100644 (file)
index 0000000..f3fea46
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        nspinstl.c
+ * PURPOSE:     Namespace Provider Installation
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCEnableNSProvider(IN LPGUID lpProviderId,
+                    IN BOOL fEnable)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCInstallNameSpace(IN LPWSTR lpszIdentifier,
+                    IN LPWSTR lpszPathName,
+                    IN DWORD dwNameSpace,
+                    IN DWORD dwVersion,
+                    IN LPGUID lpProviderId)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCUnInstallNameSpace(IN LPGUID lpProviderId)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCUpdateProvider(LPGUID lpProviderId,
+                  const WCHAR FAR * lpszProviderDllPath,
+                  const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
+                  DWORD dwNumberOfEntries,
+                  LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCWriteNameSpaceOrder(LPGUID lpProviderId,
+                       DWORD dwNumberOfEntries)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/nsprovid.c b/reactos/dll/win32/ws2_32_new/src/nsprovid.c
new file mode 100644 (file)
index 0000000..b1c8673
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        nsprovid.c
+ * PURPOSE:     Namespace Provider Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* FUNCTIONS *****************************************************************/
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqProvAllocate(VOID)
+{
+    PNSQUERY_PROVIDER Provider;
+    
+    /* Allocate the object */
+    Provider = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Provider));
+
+    /* Return it */
+    return Provider;
+}
+
+DWORD
+WSAAPI
+WsNqProvInitialize(IN PNSQUERY_PROVIDER QueryProvider,
+                   IN PNS_PROVIDER Provider)
+{
+    /* Reference the provider */
+    InterlockedIncrement(&Provider->RefCount);
+
+    /* Set it as our own */
+    QueryProvider->Provider = Provider;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+VOID
+WSAAPI
+WsNqProvDelete(IN PNSQUERY_PROVIDER QueryProvider)
+{
+    /* Check if we have a provider */
+    if (QueryProvider->Provider)
+    {
+        /* Dereference it */
+        WsNpDereference(QueryProvider->Provider);
+
+        /* Clear it */
+        QueryProvider->Provider = NULL;
+    }
+
+    /* Delete us */
+    HeapFree(WsSockHeap, 0, QueryProvider);
+}
+
+PNS_PROVIDER
+WSAAPI
+WsNpAllocate(VOID)
+{
+    PNS_PROVIDER Provider;
+    
+    /* Allocate the object */
+    Provider = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Provider));
+
+    /* Set non-null data */
+    Provider->RefCount = 1;
+    Provider->Service.cbSize = sizeof(NSP_ROUTINE);
+
+    /* Return us */
+    return Provider;
+}
+
+DWORD
+WSAAPI
+WsNpInitialize(IN PNS_PROVIDER Provider,
+               IN LPWSTR DllName,
+               IN LPGUID ProviderId)
+{
+    DWORD ExpandedPathLength, PathLength;
+    INT ErrorCode = ERROR_SUCCESS;
+    LPNSPSTARTUP NSPStartupProc;
+    CHAR AnsiPath[MAX_PATH], ExpandedDllPath[MAX_PATH];
+    
+    /* Convert the path to ANSI */
+    PathLength = WideCharToMultiByte(CP_ACP,
+                                     0,
+                                     DllName,
+                                     -1,
+                                     AnsiPath,
+                                     MAX_PATH,
+                                     NULL,
+                                     NULL);
+
+    /* Expand the DLL Path */
+    ExpandedPathLength = ExpandEnvironmentStringsA(AnsiPath,
+                                                   ExpandedDllPath,
+                                                   MAX_PATH);
+
+    /* Load the DLL */
+    Provider->DllHandle = LoadLibraryA(ExpandedDllPath);
+    if (!Provider->DllHandle)
+    {
+        /* Fail */
+        ErrorCode = WSAEPROVIDERFAILEDINIT;
+        goto Fail;
+    }
+
+    /* Get the pointer to NSPStartup */
+    NSPStartupProc = (LPNSPSTARTUP)GetProcAddress(Provider->DllHandle,
+                                                  "NSPStartup");
+    if (!NSPStartupProc)
+    {
+        /* Fail */
+        ErrorCode = WSAEPROVIDERFAILEDINIT;
+        goto Fail;
+    }
+
+    /* Call it */
+    (*NSPStartupProc)(ProviderId, (LPNSP_ROUTINE)&Provider->Service.cbSize);
+
+    /* Save the provider ID */
+    Provider->ProviderId = *ProviderId;
+    return ErrorCode;
+
+Fail:
+    /* Bail out */
+    if (Provider->DllHandle) FreeLibrary(Provider->DllHandle);
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsNpNSPCleanup(IN PNS_PROVIDER Provider)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    LPNSPCLEANUP lpNSPCleanup = NULL;
+    
+    /* Make sure we have a loaded handle */
+    if (Provider->DllHandle)
+    {
+        /* Get the pointer and clear it */
+        lpNSPCleanup = InterlockedExchangePointer((PVOID*)&Provider->Service.NSPCleanup,
+                                                  NULL);
+        /* If it's not NULL, call it */
+        if (lpNSPCleanup) ErrorCode = lpNSPCleanup(&Provider->ProviderId);
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+VOID
+WSAAPI
+WsNpDelete(IN PNS_PROVIDER Provider)
+{
+    /* Make sure we have a loaded handle */
+    if (Provider->DllHandle)
+    {
+        /* Clean us up */
+        WsNpNSPCleanup(Provider);
+
+        /* Unload the library */
+        FreeLibrary(Provider->DllHandle);
+
+        /* Clear the handle value */
+        Provider->DllHandle = NULL;
+    }
+}
+
+VOID
+WSAAPI
+WsNpDereference(IN PNS_PROVIDER Provider)
+{
+    /* Decrease the reference count and check if it's zero */
+    if (!InterlockedDecrement(&Provider->RefCount))
+    {
+        /* Delete us*/
+        WsNpDelete(Provider);
+    }
+}
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceEnd(IN PNSQUERY_PROVIDER QueryProvider)
+{
+    /* Simply call the provider */
+    return WsNpLookupServiceEnd(QueryProvider->Provider,
+                                QueryProvider->LookupHandle);
+}
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceNext(IN PNSQUERY_PROVIDER QueryProvider,
+                          IN DWORD ControlFlags,
+                          IN PDWORD BufferLength,
+                          LPWSAQUERYSETW Results)
+{
+    /* Simply call the provider */
+    return WsNpLookupServiceNext(QueryProvider->Provider,
+                                 QueryProvider->LookupHandle,
+                                 ControlFlags,
+                                 BufferLength,
+                                 Results);
+}
+
+DWORD
+WSAAPI
+WsNqProvLookupServiceBegin(IN PNSQUERY_PROVIDER QueryProvider,
+                           IN LPWSAQUERYSETW Restrictions,
+                           IN LPWSASERVICECLASSINFOW ServiceClassInfo,
+                           IN DWORD ControlFlags)
+{
+    /* Simply call the provider */
+    return WsNpLookupServiceBegin(QueryProvider->Provider,
+                                  Restrictions,
+                                  ServiceClassInfo,
+                                  ControlFlags,
+                                  &QueryProvider->LookupHandle);
+}
+
+DWORD
+WSAAPI
+WsNpLookupServiceEnd(IN PNS_PROVIDER Provider,
+                     IN HANDLE LookupHandle)
+{
+    /* Call the NSP */
+    return Provider->Service.NSPLookupServiceEnd(LookupHandle);
+}
+
+DWORD
+WSAAPI
+WsNpLookupServiceNext(IN PNS_PROVIDER Provider,
+                      IN HANDLE LookupHandle,
+                      IN DWORD ControlFlags,
+                      OUT PDWORD BufferLength,
+                      OUT LPWSAQUERYSETW Results)
+{
+    /* Call the NSP */
+    return Provider->Service.NSPLookupServiceNext(LookupHandle,
+                                                  ControlFlags,
+                                                  BufferLength,
+                                                  Results);
+}
+
+DWORD
+WSAAPI
+WsNpLookupServiceBegin(IN PNS_PROVIDER Provider,
+                       IN LPWSAQUERYSETW Restrictions,
+                       IN LPWSASERVICECLASSINFOW ServiceClassInfo,
+                       IN DWORD ControlFlags,
+                       OUT PHANDLE LookupHandle)
+{
+    /* Call the NSP */
+    return Provider->Service.NSPLookupServiceBegin(&Provider->ProviderId,
+                                                   Restrictions,
+                                                   ServiceClassInfo,
+                                                   ControlFlags,
+                                                   LookupHandle);
+}
+
diff --git a/reactos/dll/win32/ws2_32_new/src/nsquery.c b/reactos/dll/win32/ws2_32_new/src/nsquery.c
new file mode 100644 (file)
index 0000000..7b3c781
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        nsquery.c
+ * PURPOSE:     Namespace Query Object
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+#define WsNqLock()      EnterCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock);
+#define WsNqUnlock()    LeaveCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock);
+
+/* FUNCTIONS *****************************************************************/
+
+PNSQUERY
+WSAAPI
+WsNqAllocate(VOID)
+{
+    PNSQUERY NsQuery;
+    
+    /* Allocate the object */
+    NsQuery = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*NsQuery));
+
+    /* Set non-zero fields */
+    NsQuery->Signature = ~0xBEADFACE;
+    InitializeListHead(&NsQuery->ProviderList);
+    NsQuery->TryAgain = TRUE;
+    
+    /* Return it */
+    return NsQuery;
+}
+
+DWORD
+WSAAPI
+WsNqInitialize(IN PNSQUERY Query)
+{
+    /* Initialize the lock */
+    InitializeCriticalSection((LPCRITICAL_SECTION)&Query->Lock);
+
+    /* Set initial reference count and signature */
+    Query->RefCount = 1;
+    Query->Signature = 0xBEADFACE;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+BOOL
+WSAAPI
+WsNqValidateAndReference(IN PNSQUERY Query)
+{
+    /* Check the signature first */
+    if (Query->Signature != 0xBEADFACE) return FALSE;
+
+    /* Validate the reference count */
+    if (!Query->RefCount) return FALSE;
+
+    /* Increase reference count */
+    InterlockedIncrement(&Query->RefCount);
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WSAAPI
+WsNqDelete(IN PNSQUERY NsQuery)
+{
+    PNSQUERY_PROVIDER Provider;
+    PLIST_ENTRY Entry;
+    
+    /* Make sure that we got initialized */
+    if (!NsQuery->ProviderList.Flink) return;
+
+    /* Loop the provider list */
+    while (!IsListEmpty(&NsQuery->ProviderList))
+    {
+        /* Remove the entry */
+        Entry = RemoveHeadList(&NsQuery->ProviderList);
+
+        /* Get the provider */
+        Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+
+        /* Delete it */
+        WsNqProvDelete(Provider);
+    }
+
+    /* Remove the signature and delete the lock */
+    NsQuery->Signature = ~0xBEADFACE;
+    DeleteCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock);
+
+    /* Free us */
+    HeapFree(WsSockHeap, 0, NsQuery);
+}
+
+VOID
+WSAAPI
+WsNqDereference(IN PNSQUERY Query)
+{
+    /* Decrease the reference count and check if it's zero */
+    if (!InterlockedDecrement(&Query->RefCount))
+    {
+        /* Delete us*/
+        WsNqDelete(Query);
+    }
+}
+
+BOOL
+WSAAPI
+WsNqBeginEnumerationProc(PVOID Context,
+                         PNSCATALOG_ENTRY Entry)
+{
+    PNS_PROVIDER Provider;
+    BOOLEAN GoOn = TRUE;
+    PENUM_CONTEXT EnumContext = (PENUM_CONTEXT)Context;
+    PNSQUERY NsQuery = EnumContext->NsQuery;
+    DWORD NamespaceId = Entry->NamespaceId;
+
+    /* Match the namespace ID, protocols and make sure it's enabled */
+    if ((((EnumContext->lpqsRestrictions->dwNameSpace == NamespaceId) ||
+          (EnumContext->lpqsRestrictions->dwNameSpace == NS_ALL)) &&
+         (!(EnumContext->lpqsRestrictions->dwNumberOfProtocols) ||
+           (WsNcMatchProtocols(NamespaceId,
+                               Entry->AddressFamily,
+                               EnumContext->lpqsRestrictions)))) &&
+        (Entry->Enabled))
+    {
+        /* Get the provider */
+        if (!(Provider = Entry->Provider))
+        {
+            /* None was laoded, load it */
+            if ((WsNcLoadProvider(EnumContext->Catalog, Entry) != ERROR_SUCCESS))
+            {
+                /* return fake success */
+                return TRUE;
+            }
+
+            /* Set the provider */
+            Provider = Entry->Provider;
+        }
+
+        /* Add it to the query */
+        if (!(WsNqAddProvider(NsQuery, Provider)))
+        {
+            /* We failed */
+            EnumContext->ErrorCode = WSASYSCALLFAILURE;
+            GoOn = FALSE;
+        }
+    }
+
+    /* Return to caller */
+    return GoOn;
+}
+
+DWORD
+WSAAPI
+WsNqLookupServiceEnd(IN PNSQUERY NsQuery)
+{
+    PNSQUERY_PROVIDER Provider;
+    PLIST_ENTRY Entry;
+    
+    /* Protect us from closure */
+    WsNqLock();
+    NsQuery->ShuttingDown = TRUE;
+
+    /* Get the list and loop */
+    Entry = NsQuery->ProviderList.Flink;
+    while (Entry != &NsQuery->ProviderList)
+    {
+        /* Get the provider */
+        Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+
+        /* Call its routine */
+        WsNqProvLookupServiceEnd(Provider);
+
+        /* Move to the next one */
+        Entry = Entry->Flink;
+    }
+
+    /* Release lock and return success */
+    WsNqUnlock();
+    return ERROR_SUCCESS;
+}
+
+DWORD
+WSAAPI
+WsNqLookupServiceNext(IN PNSQUERY NsQuery,
+                      IN DWORD ControlFlags,
+                      OUT PDWORD BufferLength,
+                      OUT LPWSAQUERYSETW Results)
+{
+    PNSQUERY_PROVIDER Provider, NextProvider;
+    INT ErrorCode = SOCKET_ERROR, OldErrorCode;
+    PLIST_ENTRY Entry;
+
+    /* Make sure we're not shutting down */
+    if (!NsQuery->ShuttingDown)
+    {
+        /* Acquire query lock */
+        WsNqLock();
+
+        /* Check if we already have an active provider */
+        NextProvider = NsQuery->ActiveProvider;
+        if (!NextProvider)
+        {
+            /* Make sure we have a current provider */
+            if (!NsQuery->CurrentProvider)
+            {
+                /* We don't; fail */
+                WsNqUnlock();
+                SetLastError(WSA_E_NO_MORE);
+                return SOCKET_ERROR;
+            }
+
+            /* Get the first provider on the list and start looping */
+            Entry = NsQuery->ProviderList.Blink;
+            NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+            while (NextProvider)
+            {
+                /* Check if this is a new-style provider */
+                if (NextProvider->Provider->Service.NSPIoctl)
+                {
+                    /* Remove it and re-add it on top */
+                    RemoveEntryList(&NextProvider->QueryLink);
+                    InsertHeadList(&NsQuery->ProviderList, &NextProvider->QueryLink);
+
+                    /* Set it as the active provider and exit the loop */
+                    NsQuery->ActiveProvider = NextProvider;
+                    break;
+                }
+
+                /* Get the previous provider */
+                NextProvider = WsNqPreviousProvider(NsQuery, NextProvider);
+            }
+        }
+
+        /* Release the lock */
+        WsNqUnlock();
+
+        /* Check if we have an active provider now */
+        if (NextProvider)
+        {
+            /* Start loop */
+            do
+            {
+                /* Call its routine */
+                ErrorCode = WsNqProvLookupServiceNext(NextProvider,
+                                                      ControlFlags,
+                                                      BufferLength,
+                                                      Results);
+                /* Check for error or shutdown */
+                if ((ErrorCode == ERROR_SUCCESS) ||
+                    (GetLastError() == WSAEFAULT) || (NsQuery->ShuttingDown))
+                {
+                    /* Get out */
+                    break;
+                }
+
+                /* Acquire Query Lock */
+                WsNqLock();
+
+                /* Save the current active provider */
+                Provider = NsQuery->ActiveProvider;
+                
+                /* Check if one exists */
+                if (Provider)
+                {
+                    /* Get the next one */
+                    NextProvider = WsNqNextProvider(NsQuery,
+                                                    NsQuery->ActiveProvider);
+
+                    /* Was the old provider our active? */
+                    if (Provider == NsQuery->ActiveProvider)
+                    {
+                        /* Change our active provider to the new one */
+                        NsQuery->ActiveProvider = NextProvider;
+                    }
+                }
+                else
+                {
+                    /* No next provider */
+                    NextProvider = NULL;
+                }
+
+                /* Check if we failed and if we can try again */
+                if (!(NextProvider) &&
+                    (ErrorCode == SOCKET_ERROR) &&
+                    (NsQuery->TryAgain))
+                {
+                    /* Save the error code so RAS doesn't overwrite it */
+                    OldErrorCode = GetLastError();
+
+                    /* Make sure we won't try for a 3rd time */
+                    NsQuery->TryAgain = FALSE;
+
+                    /* Call the helper to auto-dial */
+                    if (WSAttemptAutodialName(NsQuery->QuerySet))
+                    {
+                        /* It suceeded, so we'll delete the current state. */
+                        while (!IsListEmpty(&NsQuery->ProviderList))
+                        {
+                            /* Remove the entry and get its provider */
+                            Entry = RemoveHeadList(&NsQuery->ProviderList);
+                            Provider = CONTAINING_RECORD(Entry,
+                                                         NSQUERY_PROVIDER,
+                                                         QueryLink);
+
+                            /* Reset it */
+                            WsNqProvLookupServiceEnd(Provider);
+                            WsNqProvDelete(Provider);
+                        }                  
+
+                        /* Start a new query */
+                        if (!WsNqLookupServiceBegin(NsQuery,
+                                                    NsQuery->QuerySet,
+                                                    NsQuery->ControlFlags,
+                                                    NsQuery->Catalog))
+                        {
+                            /* New query succeeded, set active provider now */
+                            NsQuery->ActiveProvider = 
+                                WsNqNextProvider(NsQuery,
+                                                 NsQuery->ActiveProvider);
+                        }
+                    }
+                    else
+                    {
+                        /* Reset the error code */
+                        SetLastError(OldErrorCode);
+                    }
+                }
+
+                /* Release lock */
+                WsNqUnlock();
+
+                /* Keep looping as long as there is a provider */
+            } while (NextProvider);   
+        }
+    }
+    else
+    {
+        /* We are shuting down; fail */
+        SetLastError(WSAECANCELLED);
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+DWORD
+WSAAPI
+WsNqLookupServiceBegin(IN PNSQUERY NsQuery,
+                       IN LPWSAQUERYSETW Restrictions,
+                       IN DWORD ControlFlags,
+                       IN PNSCATALOG Catalog)
+{
+    WSASERVICECLASSINFOW ClassInfo;
+    PNSQUERY_PROVIDER Provider;
+    LPWSASERVICECLASSINFOW pClassInfo = NULL;
+    PNSQUERY_PROVIDER NextProvider;
+    PLIST_ENTRY Entry;
+    INT ErrorCode;
+    DWORD ClassInfoSize;
+    PNSCATALOG_ENTRY CatalogEntry;
+    ENUM_CONTEXT EnumContext;
+    BOOLEAN TryAgain;
+
+    /* Check for RAS Auto-dial attempt */
+    if (NsQuery->TryAgain)
+    {
+        /* Make a copy of the query set */
+        ErrorCode = CopyQuerySetW(Restrictions, &NsQuery->QuerySet);
+        TryAgain = (ErrorCode == ERROR_SUCCESS);
+
+        /* Check if we'll try again */
+        if (!TryAgain)
+        {
+            /* We won't, fail */
+            SetLastError(ErrorCode);
+            ErrorCode = SOCKET_ERROR;
+            NsQuery->TryAgain = FALSE;
+            goto error;
+        }
+
+        /* Cache the information for a restart */
+        NsQuery->ControlFlags = ControlFlags;
+        NsQuery->Catalog = Catalog;
+    }
+    
+    /* Check if we have a specific ID */
+    if (Restrictions->lpNSProviderId)
+    {
+        /* Get the provider */
+        ErrorCode = WsNcGetCatalogFromProviderId(Catalog,
+                                                 Restrictions->lpNSProviderId,
+                                                 &CatalogEntry);
+        /* Check for success */
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Fail */
+            SetLastError(WSAEINVAL);
+            ErrorCode = SOCKET_ERROR;
+            goto error;
+        }
+        else
+        {
+            /* Add this provider */
+            WsNqAddProvider(NsQuery, CatalogEntry->Provider);
+        }
+    }
+    else
+    {
+        /* Setup the lookup context */
+        EnumContext.lpqsRestrictions = Restrictions;
+        EnumContext.ErrorCode = ERROR_SUCCESS;
+        EnumContext.NsQuery = NsQuery;
+        EnumContext.Catalog = Catalog;
+
+        /* Do a lookup for every entry */
+        WsNcEnumerateCatalogItems(Catalog,
+                                  WsNqBeginEnumerationProc,
+                                  &EnumContext);
+        ErrorCode = EnumContext.ErrorCode;
+        
+        /* Check for success */
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Fail */
+            SetLastError(WSAEINVAL);
+            ErrorCode = SOCKET_ERROR;
+            goto error;
+        }
+    }
+
+    /* Get the class information */
+    ClassInfo.lpServiceClassId = Restrictions->lpServiceClassId;
+    ErrorCode = WsNcGetServiceClassInfo(Catalog, &ClassInfoSize, &ClassInfo);
+
+    /* Check if more buffer space is needed */
+    if ((ErrorCode == SOCKET_ERROR) && (GetLastError() == WSAEFAULT))
+    {
+        /* FIXME: The WS 2.2 spec hasn't been finalized yet on this... */
+    }
+    else
+    {
+        /* Assume sucess */
+        ErrorCode = ERROR_SUCCESS;
+    }
+
+    /* Check if the provider list is empty */
+    if (IsListEmpty(&NsQuery->ProviderList))
+    {
+        /* We don't have any providers to handle this! */
+        ErrorCode = SOCKET_ERROR;
+        SetLastError(WSASERVICE_NOT_FOUND);
+        goto error;
+    }
+
+    /* Get the first provider and loop */
+    Entry = NsQuery->ProviderList.Flink;
+    NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+    while (NextProvider)
+    {
+        /* Call it */
+        ErrorCode = WsNqProvLookupServiceBegin(NextProvider,
+                                               Restrictions,
+                                               pClassInfo,
+                                               ControlFlags);
+        /* Check for error */
+        if (ErrorCode == SOCKET_ERROR)
+        {
+            /* Remove this provider, get the next one, delete the old one */
+            Provider = NextProvider;
+            NextProvider = WsNqNextProvider(NsQuery, NextProvider);
+            RemoveEntryList(&Provider->QueryLink);
+            WsNqProvDelete(Provider);
+        }
+        else
+        {
+            /* Get the next provider */
+            NextProvider = WsNqNextProvider(NsQuery, NextProvider);
+        }
+    }
+
+error:
+    /* Check if we had an error somewhere */
+    if (ErrorCode == SOCKET_ERROR)
+    {
+        /* Loop the list */
+        while (!IsListEmpty(&NsQuery->ProviderList))
+        {
+            /* Remove this provider */
+            Entry = RemoveHeadList(&NsQuery->ProviderList);
+
+            /* Get the failed provider and delete it */
+            Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+            WsNqProvDelete(Provider);
+        }
+    }
+    else
+    {
+        /* Set the active provider */
+        Entry = NsQuery->ProviderList.Flink;
+        NsQuery->ActiveProvider = CONTAINING_RECORD(Entry,
+                                                    NSQUERY_PROVIDER,
+                                                    QueryLink);
+    }
+
+    /* Return */
+    return ErrorCode;
+}
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqNextProvider(IN PNSQUERY Query,
+                 IN PNSQUERY_PROVIDER Provider)
+{
+    PNSQUERY_PROVIDER NextProvider = NULL;
+    PLIST_ENTRY Entry;
+    
+    /* Get the first entry and get its provider */
+    Entry = Provider->QueryLink.Flink;
+    if (Entry != &Query->ProviderList)
+    {
+        /* Get the current provider */
+        NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+    }
+
+    /* Return it */
+    return NextProvider;
+}
+
+PNSQUERY_PROVIDER
+WSAAPI
+WsNqPreviousProvider(IN PNSQUERY Query,
+                     IN PNSQUERY_PROVIDER Provider)
+{
+    PNSQUERY_PROVIDER NextProvider = NULL;
+    PLIST_ENTRY Entry;
+    
+    /* Get the first entry and get its provider */
+    Entry = Provider->QueryLink.Blink;
+    if (Entry != &Query->ProviderList)
+    {
+        /* Get the current provider */
+        NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
+    }
+
+    /* Return it */
+    return NextProvider;
+}
+
+DWORD
+WSAAPI
+WsNqAddProvider(IN PNSQUERY Query,
+                IN PNS_PROVIDER Provider)
+{
+    PNSQUERY_PROVIDER QueryProvider;
+    DWORD Return = TRUE;
+    
+    /* Allocate a new Query Provider */
+    if ((QueryProvider = WsNqProvAllocate()))
+    {
+        /* Initialize it */
+        WsNqProvInitialize(QueryProvider, Provider);
+
+        /* Insert it into the provider list */
+        InsertTailList(&Query->ProviderList, &QueryProvider->QueryLink);
+    }
+    else
+    {
+        /* We failed */
+        SetLastError(WSASYSCALLFAILURE);
+        Return = FALSE;
+    }
+
+    /* Return */
+    return Return;
+}
+
+
diff --git a/reactos/dll/win32/ws2_32_new/src/qos.c b/reactos/dll/win32/ws2_32_new/src/qos.c
new file mode 100644 (file)
index 0000000..a20b75a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        qos.c
+ * PURPOSE:     QoS Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSAGetQOSByName(IN SOCKET s, 
+                IN OUT LPWSABUF lpQOSName, 
+                OUT LPQOS lpQOS)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSAGetQOSByName: %lx, %p\n", s, lpQOSName);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPGetQOSByName(s,
+                                                                 lpQOSName,
+                                                                 lpQOS,
+                                                                 &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return FALSE;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/qshelpr.c b/reactos/dll/win32/ws2_32_new/src/qshelpr.c
new file mode 100644 (file)
index 0000000..6607274
--- /dev/null
@@ -0,0 +1,1065 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        qshelpr.c
+ * PURPOSE:     Query Set Conversion/Packing Helpers
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+LPSTR
+WSAAPI
+AnsiDupFromUnicode(IN LPWSTR UnicodeString)
+{
+    INT Length = 0;
+    BOOL GoOn = TRUE;
+    LPSTR DuplicatedString = NULL;
+    INT ReturnValue;
+
+    /* Start a loop (which should only run twice) */
+    while (GoOn)
+    {
+        /* Call the conversion function */
+        ReturnValue = WideCharToMultiByte(CP_ACP,
+                                          0,
+                                          UnicodeString,
+                                          -1,
+                                          DuplicatedString,
+                                          Length,
+                                          NULL,
+                                          NULL);
+        if (ReturnValue > Length)
+        {
+            /* This is the first loop, and we have the real size now */
+            Length = ReturnValue;
+
+            /* Allocate buffer for it */
+            DuplicatedString = HeapAlloc(WsSockHeap, 0, Length);
+            if (!DuplicatedString) GoOn = FALSE;
+        }
+        else if (ReturnValue > 0)
+        {
+            /* The second loop was sucesfull and we have the string */
+            GoOn = FALSE;
+        }
+        else
+        {
+            /* Some weird error happened */
+            if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString);
+            DuplicatedString = NULL;
+            GoOn = FALSE;
+        }
+    }
+
+    /* Return the duplicate */
+    return DuplicatedString;
+}
+
+LPWSTR
+WSAAPI
+UnicodeDupFromAnsi(IN LPSTR AnsiString)
+{
+    INT Length = 0;
+    BOOL GoOn = TRUE;
+    LPWSTR DuplicatedString = NULL;
+    INT ReturnValue;
+
+    /* Start a loop (which should only run twice) */
+    while (GoOn)
+    {
+        /* Call the conversion function */
+        ReturnValue = MultiByteToWideChar(CP_ACP,
+                                          0,
+                                          AnsiString,
+                                          -1,
+                                          DuplicatedString,
+                                          Length);
+        if (ReturnValue > Length)
+        {
+            /* This is the first loop, and we have the real size now */
+            Length = ReturnValue;
+
+            /* Allocate buffer for it */
+            DuplicatedString = HeapAlloc(WsSockHeap, 0, Length * sizeof(WCHAR));
+            if (!DuplicatedString) GoOn = FALSE;
+        }
+        else if (ReturnValue > 0)
+        {
+            /* The second loop was sucesfull and we have the string */
+            GoOn = FALSE;
+        }
+        else
+        {
+            /* Some weird error happened */
+            if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString);
+            DuplicatedString = NULL;
+            GoOn = FALSE;
+        }
+    }
+
+    /* Return the duplicate */
+    return DuplicatedString;
+}
+
+SIZE_T
+WSAAPI
+ComputeStringSize(IN LPSTR String,
+                  IN BOOLEAN IsUnicode)
+{
+    /* Return the size of the string, in bytes, including null-char */
+    return (IsUnicode) ? (wcslen((LPWSTR)String) + 1 ) * sizeof(WCHAR) :
+                          strlen(String) + sizeof(CHAR);
+}
+
+SIZE_T
+WSAAPI
+ComputeQuerySetSize(IN LPWSAQUERYSETA AnsiSet,
+                    IN BOOLEAN IsUnicode)
+{
+    SIZE_T Size = sizeof(WSAQUERYSETA);
+    //LPWSAQUERYSETW UnicodeSet = (LPWSAQUERYSETW)AnsiSet;
+    DWORD i;
+
+    /* Check for instance name */
+    if (AnsiSet->lpszServiceInstanceName)
+    {
+        /* Add its size */
+        Size += ComputeStringSize(AnsiSet->lpszServiceInstanceName, IsUnicode);
+    }
+
+    /* Check for Service Class ID */
+    if (AnsiSet->lpServiceClassId)
+    {
+        /* Align the current size and add GUID size */
+        Size = (Size + 3) & ~3;
+        Size += sizeof(GUID);
+    }
+
+    /* Check for version data */
+    if (AnsiSet->lpVersion)
+    {
+        /* Align the current size and add GUID size */
+        Size = (Size + 3) & ~3;
+        Size += sizeof(WSAVERSION);
+    }
+
+    /* Check for comment */
+    if (AnsiSet->lpszComment)
+    {
+        /* Align the current size and add string size */
+        Size = (Size + 1) & ~1;
+        Size += ComputeStringSize(AnsiSet->lpszComment, IsUnicode);
+    }
+
+    /* Check for Provider ID */
+    if (AnsiSet->lpNSProviderId)
+    {
+        /* Align the current size and add GUID size */
+        Size = (Size + 3) & ~3;
+        Size += sizeof(GUID);
+    }
+
+    /* Check for context */
+    if (AnsiSet->lpszContext)
+    {
+        /* Align the current size and add string size */
+        Size = (Size + 1) & ~1;
+        Size += ComputeStringSize(AnsiSet->lpszContext, IsUnicode);
+    }
+
+    /* Check for query string */
+    if (AnsiSet->lpszQueryString)
+    {
+        /* Align the current size and add string size */
+        Size = (Size + 1) & ~1;
+        Size += ComputeStringSize(AnsiSet->lpszQueryString, IsUnicode);
+    }
+
+    /* Check for AF Protocol data */
+    if (AnsiSet->lpafpProtocols)
+    {
+        /* Align the current size and add AFP size */
+        Size = (Size + 3) & ~3;
+        Size += sizeof(AFPROTOCOLS) * AnsiSet->dwNumberOfProtocols;
+    }
+
+    /* Check for CSADDR buffer */
+    if (AnsiSet->lpcsaBuffer)
+    {
+        /* Align the current size */
+        Size = (Size + 3) & ~3;
+
+        /* Loop all the addresses in the array */
+        for (i = 0; i < AnsiSet->dwNumberOfCsAddrs; i++)
+        {
+            /* Check for local sockaddr */
+            if (&AnsiSet->lpcsaBuffer[i].LocalAddr)
+            {
+                /* Align the current size and add the sockaddr's length */
+                Size = (Size + 3) & ~3; 
+                Size += AnsiSet->lpcsaBuffer[i].LocalAddr.iSockaddrLength;
+            }
+            /* Check for remote sockaddr */
+            if (&AnsiSet->lpcsaBuffer[i].RemoteAddr)
+            {
+                /* Align the current size and add the sockaddr's length */
+                Size = (Size + 3) & ~3; 
+                Size += AnsiSet->lpcsaBuffer[i].RemoteAddr.iSockaddrLength;
+            }
+
+            /* Add the sockaddr size itself */
+            Size += sizeof(CSADDR_INFO);
+        }
+    }
+
+    /* Check for blob data */
+    if (AnsiSet->lpBlob)
+    {
+        /* Align the current size and add blob size */
+        Size = (Size + 3) & ~3;
+        Size += sizeof(BLOB);
+
+        /* Also add the actual blob data size, if it exists */
+        if (AnsiSet->lpBlob) Size += AnsiSet->lpBlob->cbSize;
+    }
+
+    /* Return the total size */
+    return Size;
+}
+
+SIZE_T
+WSAAPI
+WSAComputeQuerySetSizeA(IN LPWSAQUERYSETA AnsiSet)
+{
+    /* Call the generic helper */
+    return ComputeQuerySetSize(AnsiSet, FALSE);
+}
+
+SIZE_T
+WSAAPI
+WSAComputeQuerySetSizeW(IN LPWSAQUERYSETW UnicodeSet)
+{
+    /* Call the generic helper */
+    return ComputeQuerySetSize((LPWSAQUERYSETA)UnicodeSet, TRUE);
+}
+
+PVOID
+WSAAPI
+WsBufferAllocate(IN PWS_BUFFER Buffer,
+                 IN SIZE_T Size,
+                 IN DWORD Align)
+{
+    PVOID NewPosition;
+
+    /* Align the current usage */
+    Buffer->BytesUsed = (Buffer->BytesUsed + Align - 1) & ~(Align - 1);
+
+    /* Update our location */
+    NewPosition = (PVOID)(Buffer->Position + Buffer->BytesUsed);
+
+    /* Update the usage */
+    Buffer->BytesUsed += Size;
+
+    /* Return new location */
+    return NewPosition;
+}
+
+VOID
+WSAAPI
+CopyBlobIndirect(IN PWS_BUFFER Buffer,
+                 IN OUT LPBLOB RelativeBlob,
+                 IN LPBLOB Blob)
+{
+    /* Make sure we have blob data */
+    if ((Blob->pBlobData) && (Blob->cbSize))
+    {
+        /* Allocate and copy the blob data */
+        RelativeBlob->pBlobData = WsBufferAllocate(Buffer,
+                                                   Blob->cbSize,
+                                                   sizeof(PVOID));
+        RtlCopyMemory(RelativeBlob->pBlobData,
+                      Blob->pBlobData,
+                      Blob->cbSize);
+    }
+}
+
+VOID
+WSAAPI
+CopyAddrInfoArrayIndirect(IN PWS_BUFFER Buffer,
+                          IN OUT LPCSADDR_INFO RelativeCsaddr,
+                          IN DWORD Addresses,
+                          IN LPCSADDR_INFO Csaddr)
+{
+    DWORD i;
+
+    /* Loop for every address inside */
+    for (i = 0; i < Addresses; i++)
+    {
+        /* Check for a local address */
+        if ((Csaddr[i].LocalAddr.lpSockaddr) &&
+            (Csaddr[i].LocalAddr.iSockaddrLength))
+        {
+            /* Allocate and copy the address */
+            RelativeCsaddr[i].LocalAddr.lpSockaddr =
+                WsBufferAllocate(Buffer,
+                                 Csaddr[i].LocalAddr.iSockaddrLength,
+                                 sizeof(PVOID));
+            RtlCopyMemory(RelativeCsaddr[i].LocalAddr.lpSockaddr,
+                          Csaddr[i].LocalAddr.lpSockaddr,
+                          Csaddr[i].LocalAddr.iSockaddrLength);
+        }
+        else
+        {
+            /* Nothing in this address */
+            Csaddr[i].LocalAddr.lpSockaddr = NULL;
+            Csaddr[i].LocalAddr.iSockaddrLength = 0;
+        }
+
+        /* Check for a remote address */
+        if ((Csaddr[i].RemoteAddr.lpSockaddr) &&
+            (Csaddr[i].RemoteAddr.iSockaddrLength))
+        {
+            /* Allocate and copy the address */
+            RelativeCsaddr[i].RemoteAddr.lpSockaddr =
+                WsBufferAllocate(Buffer,
+                                 Csaddr[i].RemoteAddr.iSockaddrLength,
+                                 sizeof(PVOID));
+            RtlCopyMemory(RelativeCsaddr[i].RemoteAddr.lpSockaddr,
+                          Csaddr[i].RemoteAddr.lpSockaddr,
+                          Csaddr[i].RemoteAddr.iSockaddrLength);
+        }
+        else
+        {
+            /* Nothing in this address */
+            Csaddr[i].RemoteAddr.lpSockaddr = NULL;
+            Csaddr[i].RemoteAddr.iSockaddrLength = 0;
+        }
+    }
+}
+
+VOID
+WSAAPI
+CopyQuerySetIndirectA(IN PWS_BUFFER Buffer,
+                      IN OUT LPWSAQUERYSETA RelativeSet,
+                      IN LPWSAQUERYSETA AnsiSet)
+{
+    LPSTR AnsiString;
+
+    /* Get the service name */
+    AnsiString = AnsiSet->lpszServiceInstanceName;
+    if (AnsiString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer,
+                                                                strlen(AnsiString) + 1,
+                                                                sizeof(CHAR));
+        /* Copy it into the buffer */
+        strcpy(RelativeSet->lpszServiceInstanceName, AnsiString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszServiceInstanceName = NULL;
+    }
+
+    /* Check for the service class ID */
+    if (AnsiSet->lpServiceClassId)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer,
+                                                         sizeof(GUID),
+                                                         sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpServiceClassId) = *(AnsiSet->lpServiceClassId);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpServiceClassId = NULL;
+    }
+
+    /* Get the version data */
+    if (AnsiSet->lpVersion)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpVersion = WsBufferAllocate(Buffer,
+                                                  sizeof(WSAVERSION),
+                                                  sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpVersion) = *(AnsiSet->lpVersion);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpVersion = NULL;
+    }
+
+    /* Get the comment */
+    AnsiString = AnsiSet->lpszComment;
+    if (AnsiString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszComment = WsBufferAllocate(Buffer,
+                                                    strlen(AnsiString) + 1,
+                                                    sizeof(CHAR));
+        /* Copy it into the buffer */
+        strcpy(RelativeSet->lpszComment, AnsiString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszComment = NULL;
+    }
+
+    /* Get the NS Provider ID */
+    if (AnsiSet->lpNSProviderId)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer,
+                                                       sizeof(GUID),
+                                                       sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpNSProviderId) = *(AnsiSet->lpNSProviderId);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpNSProviderId = NULL;
+    }
+
+    /* Get the context */
+    AnsiString = AnsiSet->lpszContext;
+    if (AnsiString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszContext = WsBufferAllocate(Buffer,
+                                                    strlen(AnsiString) + 1,
+                                                    sizeof(CHAR));
+        /* Copy it into the buffer */
+        strcpy(RelativeSet->lpszContext, AnsiString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszContext = NULL;
+    }
+
+    /* Get the query string */
+    AnsiString = AnsiSet->lpszQueryString;
+    if (AnsiString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszQueryString = WsBufferAllocate(Buffer,
+                                                        strlen(AnsiString) + 1,
+                                                        sizeof(CHAR));
+        /* Copy it into the buffer */
+        strcpy(RelativeSet->lpszQueryString, AnsiString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszQueryString = NULL;
+    }
+
+    /* Check for a protocol structure with non-zero protocols */
+    if ((AnsiSet->lpafpProtocols) && (AnsiSet->dwNumberOfProtocols))
+    {
+        /* One exists, allocate space for it */
+        RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer,
+                                                       AnsiSet->dwNumberOfProtocols *
+                                                       sizeof(AFPROTOCOLS),
+                                                       sizeof(PVOID));
+        /* Copy it into the buffer */
+        RtlCopyMemory(RelativeSet->lpafpProtocols,
+                      AnsiSet->lpafpProtocols,
+                      AnsiSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS));
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpafpProtocols = NULL;
+        RelativeSet->dwNumberOfProtocols = 0;
+    }
+
+    /* Check if we have a CSADDR with addresses inside */
+    if ((AnsiSet->lpcsaBuffer) && (AnsiSet->dwNumberOfCsAddrs))
+    {
+        /* Allocate and copy the CSADDR structure itself */
+        RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer,
+                                                    AnsiSet->dwNumberOfCsAddrs *
+                                                    sizeof(CSADDR_INFO),
+                                                    sizeof(PVOID));
+
+        /* Copy it into the buffer */
+        RtlCopyMemory(RelativeSet->lpafpProtocols,
+                      AnsiSet->lpafpProtocols,
+                      AnsiSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO));
+
+        /* Copy the addresses inside the CSADDR */
+        CopyAddrInfoArrayIndirect(Buffer,
+                                  RelativeSet->lpcsaBuffer,
+                                  AnsiSet->dwNumberOfCsAddrs,
+                                  AnsiSet->lpcsaBuffer);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpcsaBuffer = NULL;
+        RelativeSet->dwNumberOfCsAddrs = 0;
+    }
+
+    /* Check for blob data */
+    if (AnsiSet->lpBlob)
+    {
+        /* Allocate and copy the blob itself */
+        RelativeSet->lpBlob = WsBufferAllocate(Buffer,
+                                               sizeof(BLOB),
+                                               sizeof(PVOID));
+        *(RelativeSet->lpBlob) = *(AnsiSet->lpBlob);
+
+        /* Copy the data inside the blob */
+        CopyBlobIndirect(Buffer, RelativeSet->lpBlob, AnsiSet->lpBlob);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpBlob = NULL;
+    }
+}
+
+VOID
+WSAAPI
+CopyQuerySetIndirectW(IN PWS_BUFFER Buffer,
+                      IN OUT LPWSAQUERYSETW RelativeSet,
+                      IN LPWSAQUERYSETW UnicodeSet)
+{
+    LPWSTR UnicodeString;
+
+    /* Get the service name */
+    UnicodeString = UnicodeSet->lpszServiceInstanceName;
+    if (UnicodeString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer,
+                                                                (wcslen(UnicodeString) + 1) *
+                                                                sizeof(WCHAR),
+                                                                sizeof(CHAR));
+        /* Copy it into the buffer */
+        wcscpy(RelativeSet->lpszServiceInstanceName, UnicodeString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszServiceInstanceName = NULL;
+    }
+
+    /* Check for the service class ID */
+    if (UnicodeSet->lpServiceClassId)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer,
+                                                         sizeof(GUID),
+                                                         sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpServiceClassId) = *(UnicodeSet->lpServiceClassId);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpServiceClassId = NULL;
+    }
+
+    /* Get the version data */
+    if (UnicodeSet->lpVersion)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpVersion = WsBufferAllocate(Buffer,
+                                                  sizeof(WSAVERSION),
+                                                  sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpVersion) = *(UnicodeSet->lpVersion);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpVersion = NULL;
+    }
+
+    /* Get the comment */
+    UnicodeString = UnicodeSet->lpszComment;
+    if (UnicodeString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszComment = WsBufferAllocate(Buffer,
+                                                    (wcslen(UnicodeString) + 1) *
+                                                    sizeof(WCHAR),
+                                                    sizeof(CHAR));
+        /* Copy it into the buffer */
+        wcscpy(RelativeSet->lpszComment, UnicodeString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszComment = NULL;
+    }
+
+    /* Get the NS Provider ID */
+    if (UnicodeSet->lpNSProviderId)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer,
+                                                       sizeof(GUID),
+                                                       sizeof(PVOID));
+        /* Copy it into the buffer */
+        *(RelativeSet->lpNSProviderId) = *(UnicodeSet->lpNSProviderId);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpNSProviderId = NULL;
+    }
+
+    /* Get the context */
+    UnicodeString = UnicodeSet->lpszContext;
+    if (UnicodeString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszContext = WsBufferAllocate(Buffer,
+                                                    (wcslen(UnicodeString) + 1) *
+                                                    sizeof(WCHAR),
+                                                    sizeof(CHAR));
+        /* Copy it into the buffer */
+        wcscpy(RelativeSet->lpszContext, UnicodeString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszContext = NULL;
+    }
+
+    /* Get the query string */
+    UnicodeString = UnicodeSet->lpszQueryString;
+    if (UnicodeString)
+    {
+        /* One exists, allocate a space in the buffer for it */
+        RelativeSet->lpszQueryString = WsBufferAllocate(Buffer,
+                                                        (wcslen(UnicodeString) + 1) *
+                                                        sizeof(WCHAR),
+                                                        sizeof(CHAR));
+        /* Copy it into the buffer */
+        wcscpy(RelativeSet->lpszQueryString, UnicodeString);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpszQueryString = NULL;
+    }
+
+    /* Check for a protocol structure with non-zero protocols */
+    if ((UnicodeSet->lpafpProtocols) && (UnicodeSet->dwNumberOfProtocols))
+    {
+        /* One exists, allocate space for it */
+        RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer,
+                                                       UnicodeSet->dwNumberOfProtocols *
+                                                       sizeof(AFPROTOCOLS),
+                                                       sizeof(PVOID));
+        /* Copy it into the buffer */
+        RtlCopyMemory(RelativeSet->lpafpProtocols,
+                      UnicodeSet->lpafpProtocols,
+                      UnicodeSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS));
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpafpProtocols = NULL;
+        RelativeSet->dwNumberOfProtocols = 0;
+    }
+
+    /* Check if we have a CSADDR with addresses inside */
+    if ((UnicodeSet->lpcsaBuffer) && (UnicodeSet->dwNumberOfCsAddrs))
+    {
+        /* Allocate and copy the CSADDR structure itself */
+        RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer,
+                                                    UnicodeSet->dwNumberOfCsAddrs *
+                                                    sizeof(CSADDR_INFO),
+                                                    sizeof(PVOID));
+
+        /* Copy it into the buffer */
+        RtlCopyMemory(RelativeSet->lpafpProtocols,
+                      UnicodeSet->lpafpProtocols,
+                      UnicodeSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO));
+
+        /* Copy the addresses inside the CSADDR */
+        CopyAddrInfoArrayIndirect(Buffer,
+                                  RelativeSet->lpcsaBuffer,
+                                  UnicodeSet->dwNumberOfCsAddrs,
+                                  UnicodeSet->lpcsaBuffer);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpcsaBuffer = NULL;
+        RelativeSet->dwNumberOfCsAddrs = 0;
+    }
+
+    /* Check for blob data */
+    if (UnicodeSet->lpBlob)
+    {
+        /* Allocate and copy the blob itself */
+        RelativeSet->lpBlob = WsBufferAllocate(Buffer,
+                                               sizeof(BLOB),
+                                               sizeof(PVOID));
+        *(RelativeSet->lpBlob) = *(UnicodeSet->lpBlob);
+
+        /* Copy the data inside the blob */
+        CopyBlobIndirect(Buffer, RelativeSet->lpBlob, UnicodeSet->lpBlob);
+    }
+    else
+    {
+        /* Nothing in the buffer */
+        RelativeSet->lpBlob = NULL;
+    }
+}
+
+INT
+WSAAPI
+WSABuildQuerySetBufferA(IN LPWSAQUERYSETA AnsiSet,
+                        IN SIZE_T BufferSize,
+                        OUT LPWSAQUERYSETA RelativeSet)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    SIZE_T SetSize;
+    WS_BUFFER Buffer;
+    LPWSAQUERYSETA NewSet;
+
+    /* Find out how big the set really is */
+    SetSize = WSAComputeQuerySetSizeA(AnsiSet);
+    if (SetSize <= BufferSize)
+    {
+        /* Configure the buffer */
+        Buffer.Position = (ULONG_PTR)RelativeSet;
+        Buffer.MaxSize = SetSize;
+        Buffer.BytesUsed = 0;
+
+        /* Copy the set itself into the buffer */
+        NewSet = WsBufferAllocate(&Buffer, sizeof(*AnsiSet), sizeof(PVOID));
+        *NewSet = *AnsiSet;
+
+        /* Now copy the data inside */
+        CopyQuerySetIndirectA(&Buffer, NewSet, AnsiSet);
+    }
+    else
+    {
+        /* We failed */
+        ErrorCode = SOCKET_ERROR;
+    }
+
+    /* Return to caller */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WSABuildQuerySetBufferW(IN LPWSAQUERYSETW UnicodeSet,
+                        IN SIZE_T BufferSize,
+                        OUT LPWSAQUERYSETW RelativeSet)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    SIZE_T SetSize;
+    WS_BUFFER Buffer;
+    LPWSAQUERYSETW NewSet;
+
+    /* Find out how big the set really is */
+    SetSize = WSAComputeQuerySetSizeW(UnicodeSet);
+    if (SetSize <= BufferSize)
+    {
+        /* Configure the buffer */
+        Buffer.Position = (ULONG_PTR)RelativeSet;
+        Buffer.MaxSize = SetSize;
+        Buffer.BytesUsed = 0;
+
+        /* Copy the set itself into the buffer */
+        NewSet = WsBufferAllocate(&Buffer, sizeof(*UnicodeSet), sizeof(PVOID));
+        *NewSet = *UnicodeSet;
+
+        /* Now copy the data inside */
+        CopyQuerySetIndirectW(&Buffer, NewSet, UnicodeSet);
+    }
+    else
+    {
+        /* We failed */
+        ErrorCode = SOCKET_ERROR;
+    }
+
+    /* Return to caller */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+MapAnsiQuerySetToUnicode(IN LPWSAQUERYSETA AnsiSet,
+                         IN OUT PSIZE_T SetSize,
+                         OUT LPWSAQUERYSETW UnicodeSet)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    SIZE_T AnsiSize, UnicodeSize;
+    LPWSAQUERYSETA AnsiCopy = NULL;
+    LPWSAQUERYSETW UnicodeCopy;
+    LPWSTR ServiceCopy = NULL, CommentCopy = NULL;
+    LPWSTR ContextCopy = NULL, QueryCopy = NULL;
+
+    /* Calculate the size of the Ansi version and allocate space for a copy */
+    AnsiSize = WSAComputeQuerySetSizeA(AnsiSet);
+    AnsiCopy = HeapAlloc(WsSockHeap, 0, AnsiSize);
+    if (!AnsiCopy)
+    {
+        /* Fail, couldn't allocate memory */
+        ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+        goto error;
+    }
+    
+    /* Build the relative buffer version */
+    ErrorCode = WSABuildQuerySetBufferA(AnsiSet, AnsiSize, AnsiCopy);
+    if (ErrorCode != ERROR_SUCCESS) goto error;
+        
+    /* Re-use the ANSI version since the fields match */
+    UnicodeCopy = (LPWSAQUERYSETW)AnsiCopy;
+
+    /* Check if we have a service instance name */
+    if (AnsiCopy->lpszServiceInstanceName)
+    {
+        /* Duplicate it into unicode form */
+        ServiceCopy = UnicodeDupFromAnsi(AnsiCopy->lpszServiceInstanceName);
+        if (!ServiceCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        UnicodeCopy->lpszServiceInstanceName = ServiceCopy;
+    }
+
+    /* Check if we have a service instance name */
+    if (AnsiCopy->lpszContext)
+    {
+        /* Duplicate it into unicode form */
+        ContextCopy = UnicodeDupFromAnsi(AnsiCopy->lpszContext);
+        if (!ContextCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        UnicodeCopy->lpszContext = ContextCopy;
+    }
+
+    /* Check if we have a service instance name */
+    if (AnsiCopy->lpszComment)
+    {
+        /* Duplicate it into unicode form */
+        CommentCopy = UnicodeDupFromAnsi(AnsiCopy->lpszComment);
+        if (!CommentCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        UnicodeCopy->lpszComment = CommentCopy;
+    }
+
+    /* Check if we have a query name */
+    if (AnsiCopy->lpszQueryString)
+    {
+        /* Duplicate it into unicode form */
+        QueryCopy = UnicodeDupFromAnsi(AnsiCopy->lpszQueryString);
+        if (!QueryCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        UnicodeCopy->lpszQueryString = QueryCopy;
+    }
+
+    /* Now that we have the absolute unicode buffer, calculate its size */
+    UnicodeSize = WSAComputeQuerySetSizeW(UnicodeCopy);
+    if (UnicodeSize > *SetSize)
+    {
+        /* The buffer wasn't large enough; return how much we need */
+        *SetSize = UnicodeSize;
+        ErrorCode = WSAEFAULT;
+        goto error;
+    }
+
+    /* Build the relative unicode buffer */
+    ErrorCode = WSABuildQuerySetBufferW(UnicodeCopy, *SetSize, UnicodeSet);
+
+error:
+    /* Free the Ansi copy if we had one */
+    if (AnsiCopy) HeapFree(WsSockHeap, 0, AnsiCopy);
+
+    /* Free all the strings */
+    if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy);
+    if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy);
+    if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy);
+    if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy);
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+MapUnicodeQuerySetToAnsi(OUT LPWSAQUERYSETW UnicodeSet,
+                         IN OUT PSIZE_T SetSize,
+                         IN LPWSAQUERYSETA AnsiSet)
+{
+    INT ErrorCode = ERROR_SUCCESS;
+    SIZE_T UnicodeSize, AnsiSize;
+    LPWSAQUERYSETW UnicodeCopy = NULL;
+    LPWSAQUERYSETA AnsiCopy;
+    LPSTR ServiceCopy = NULL, CommentCopy = NULL;
+    LPSTR ContextCopy = NULL, QueryCopy = NULL;
+
+    /* Calculate the size of the Ansi version and allocate space for a copy */
+    UnicodeSize = WSAComputeQuerySetSizeW(UnicodeSet);
+    UnicodeCopy = HeapAlloc(WsSockHeap, 0, UnicodeSize);
+    if (!UnicodeCopy)
+    {
+        /* Fail, couldn't allocate memory */
+        ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+        goto error;
+    }
+    
+    /* Build the relative buffer version */
+    ErrorCode = WSABuildQuerySetBufferW(UnicodeSet, UnicodeSize, UnicodeCopy);
+    if (ErrorCode != ERROR_SUCCESS) goto error;
+        
+    /* Re-use the Unicode version since the fields match */
+    AnsiCopy = (LPWSAQUERYSETA)UnicodeCopy;
+
+    /* Check if we have a service instance name */
+    if (UnicodeCopy->lpszServiceInstanceName)
+    {
+        /* Duplicate it into unicode form */
+        ServiceCopy = AnsiDupFromUnicode(UnicodeCopy->lpszServiceInstanceName);
+        if (!ServiceCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        AnsiCopy->lpszServiceInstanceName = ServiceCopy;
+    }
+
+    /* Check if we have a service instance name */
+    if (UnicodeCopy->lpszContext)
+    {
+        /* Duplicate it into unicode form */
+        ContextCopy = AnsiDupFromUnicode(UnicodeCopy->lpszContext);
+        if (!ContextCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        AnsiCopy->lpszContext = ContextCopy;
+    }
+
+    /* Check if we have a service instance name */
+    if (UnicodeCopy->lpszComment)
+    {
+        /* Duplicate it into unicode form */
+        CommentCopy = AnsiDupFromUnicode(UnicodeCopy->lpszComment);
+        if (!CommentCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        AnsiCopy->lpszComment = CommentCopy;
+    }
+
+    /* Check if we have a query name */
+    if (UnicodeCopy->lpszQueryString)
+    {
+        /* Duplicate it into unicode form */
+        QueryCopy = AnsiDupFromUnicode(UnicodeCopy->lpszQueryString);
+        if (!QueryCopy)
+        {
+            /* Fail */
+            ErrorCode = WSA_NOT_ENOUGH_MEMORY;
+            goto error;
+        }
+
+        /* Set the new string pointer */
+        AnsiCopy->lpszQueryString = QueryCopy;
+    }
+
+    /* Now that we have the absolute unicode buffer, calculate its size */
+    AnsiSize = WSAComputeQuerySetSizeA(AnsiCopy);
+    if (AnsiSize > *SetSize)
+    {
+        /* The buffer wasn't large enough; return how much we need */
+        *SetSize = AnsiSize;
+        ErrorCode = WSAEFAULT;
+        goto error;
+    }
+
+    /* Build the relative unicode buffer */
+    ErrorCode = WSABuildQuerySetBufferA(AnsiCopy, *SetSize, AnsiSet);
+
+error:
+    /* Free the Ansi copy if we had one */
+    if (UnicodeCopy) HeapFree(WsSockHeap, 0, UnicodeCopy);
+
+    /* Free all the strings */
+    if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy);
+    if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy);
+    if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy);
+    if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy);
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet,
+              OUT LPWSAQUERYSETW *UnicodeCopy)
+{
+    SIZE_T SetSize;
+
+    /* Get the size */
+    SetSize = WSAComputeQuerySetSizeW(UnicodeSet);
+
+    /* Allocate memory for copy */
+    *UnicodeCopy = HeapAlloc(WsSockHeap, 0, SetSize);
+    if (!(*UnicodeCopy)) return WSA_NOT_ENOUGH_MEMORY;
+
+    /* Build a copy and return */
+    return WSABuildQuerySetBufferW(UnicodeSet, SetSize, *UnicodeCopy);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/rasdial.c b/reactos/dll/win32/ws2_32_new/src/rasdial.c
new file mode 100644 (file)
index 0000000..f1f620a
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        rasdial.c
+ * PURPOSE:     RAS Auto-Dial Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+typedef BOOL
+(WSAAPI *PWS_ATTEMPT_AUTODIAL_ADDR)(
+    IN CONST SOCKADDR FAR *Name,
+    IN INT NameLength
+);
+
+typedef BOOL
+(WSAAPI *PWS_ATTEMPT_AUTODIAL_NAME)(IN CONST LPWSAQUERYSETW lpqsRestrictions);
+
+typedef VOID
+(WSAAPI *PWS_NOTE_SUCCESSFUL_HOSTENT_LOOKUP)(
+    IN CONST CHAR FAR *Name,
+    IN CONST ULONG Address
+);
+
+BOOLEAN WsRasInitialized;
+HINSTANCE WsRasDllHandle;
+CRITICAL_SECTION WsRasHelperLock;
+PWS_ATTEMPT_AUTODIAL_ADDR lpfnWSAttemptAutodialAddr;
+PWS_ATTEMPT_AUTODIAL_NAME lpfnWSAttemptAutodialName;
+PWS_NOTE_SUCCESSFUL_HOSTENT_LOOKUP lpfnWSNoteSuccessfulHostentLookup;
+
+#define WsRasLock()          EnterCriticalSection(&WsRasHelperLock);
+#define WsRasUnlock()        LeaveCriticalSection(&WsRasHelperLock);
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WSAAPI
+WsRasInitializeAutodial(VOID)
+{
+    /* Initialize the autodial lock */
+    InitializeCriticalSection(&WsRasHelperLock);
+}
+
+VOID
+WSAAPI
+WsRasUninitializeAutodial(VOID)
+{
+    /* Acquire lock */
+    WsRasLock();
+
+    /* Free the library if it's loaded */
+    if (WsRasDllHandle) FreeLibrary(WsRasDllHandle);
+    WsRasDllHandle = NULL;
+
+    /* Release and delete lock */
+    WsRasUnlock();
+    DeleteCriticalSection(&WsRasHelperLock);
+}
+
+INT
+WSAAPI
+WsRasLoadHelperDll(VOID)
+{
+    CHAR HelperPath[MAX_PATH];
+    HKEY WinsockKey;
+    INT ErrorCode;
+    DWORD RegType = REG_SZ;
+    DWORD RegSize = MAX_PATH;
+
+    /* Acquire the lock */
+    WsRasLock();
+
+    /* Check if we were already initialiazed */
+    if (!WsRasInitialized)
+    {
+        /* Open the registry root key */
+        WinsockKey = WsOpenRegistryRoot();
+        if (WinsockKey)
+        {
+            /* Read the helper's location */
+            ErrorCode = RegQueryValueEx(WinsockKey,
+                                        "AutodialDLL",
+                                        0,
+                                        &RegType,
+                                        (LPBYTE)&HelperPath,
+                                        &RegSize);
+            RegCloseKey(WinsockKey);
+
+            /* Make sure we read the path */
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* Now load it */
+                WsRasDllHandle = LoadLibrary(HelperPath);
+            }
+        }
+
+        /* Check if we weren't able to load it and load the default */
+        if (!WsRasDllHandle) WsRasDllHandle = LoadLibrary("rasadhlp.dll");
+
+        /* Check again if we loaded it */
+        if (WsRasDllHandle)
+        {
+            /* Get function pointers */
+            lpfnWSAttemptAutodialAddr = 
+                (PVOID)GetProcAddress(WsRasDllHandle,
+                                      "WSAttemptAutodialAddr");
+            lpfnWSAttemptAutodialName = 
+                (PVOID)GetProcAddress(WsRasDllHandle,
+                                      "WSAttemptAutodialName");
+            lpfnWSNoteSuccessfulHostentLookup = 
+                (PVOID)GetProcAddress(WsRasDllHandle,
+                                      "WSNoteSuccessfulHostentLookup");
+        }
+
+        /* Mark us as loaded */
+        WsRasInitialized = TRUE;
+    }
+
+    /* Release lock */
+    WsRasUnlock();
+
+    /* Return status */
+    return WsRasInitialized;
+}
+
+BOOL
+WSAAPI
+WSAttemptAutodialAddr(IN CONST SOCKADDR FAR *Name,
+                      IN INT NameLength)
+{
+    /* Load the helper DLL and make sure it exports this routine */
+    if (!(WsRasLoadHelperDll()) || !(lpfnWSAttemptAutodialAddr)) return FALSE;
+
+    /* Call the function in the helper */
+    return lpfnWSAttemptAutodialAddr(Name, NameLength);
+}
+
+BOOL
+WSAAPI
+WSAttemptAutodialName(IN CONST LPWSAQUERYSETW lpqsRestrictions)
+{
+    /* Load the helper DLL and make sure it exports this routine */
+    if (!(WsRasLoadHelperDll()) || !(lpfnWSAttemptAutodialName)) return FALSE;
+
+    /* Call the function in the helper */
+    return lpfnWSAttemptAutodialName(lpqsRestrictions);
+}
+
+VOID
+WSAAPI
+WSNoteSuccessfulHostentLookup(IN CONST CHAR FAR *Name,
+                              IN CONST ULONG Address)
+{
+    /* Load the helper DLL and make sure it exports this routine */
+    if (!(WsRasLoadHelperDll()) || !(lpfnWSNoteSuccessfulHostentLookup)) return;
+
+    /* Call the function in the helper */
+    lpfnWSNoteSuccessfulHostentLookup(Name, Address);
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/recv.c b/reactos/dll/win32/ws2_32_new/src/recv.c
new file mode 100644 (file)
index 0000000..6c887c9
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        recv.c
+ * PURPOSE:     Socket Receive Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+recv(IN SOCKET s,
+     OUT CHAR FAR* buf,
+     IN INT len,
+     IN INT flags)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    WSABUF Buffers;
+    DWORD BytesReceived;
+    DPRINT("recv: %lx, %lx, %lx, %p\n", s, flags, len, buf);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Setup the buffers */
+            Buffers.buf = buf;
+            Buffers.len = len;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPRecv(s,
+                                                         &Buffers, 
+                                                         1,
+                                                         &BytesReceived, 
+                                                         (LPDWORD)&flags, 
+                                                         NULL,
+                                                         NULL, 
+                                                         ThreadId, 
+                                                         &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS)
+            {
+                /* Handle OOB */
+                if (!(flags & MSG_PARTIAL)) return BytesReceived;
+                ErrorCode = WSAEMSGSIZE;
+            }
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+recvfrom(IN SOCKET s,
+         OUT CHAR FAR* buf,
+         IN INT len,
+         IN INT flags,
+         OUT LPSOCKADDR from,
+         IN OUT INT FAR* fromlen)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    WSABUF Buffers;
+    DWORD BytesReceived;
+    DPRINT("recvfrom: %lx, %lx, %lx, %p\n", s, flags, len, buf);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Setup the buffers */
+            Buffers.buf = buf;
+            Buffers.len = len;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPRecvFrom(s,
+                                                             &Buffers, 
+                                                             1,
+                                                             &BytesReceived, 
+                                                             (LPDWORD)&flags,
+                                                             from,
+                                                             fromlen,
+                                                             NULL,
+                                                             NULL, 
+                                                             ThreadId, 
+                                                             &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS)
+            {
+                /* Handle OOB */
+                if (!(flags & MSG_PARTIAL)) return BytesReceived;
+                ErrorCode = WSAEMSGSIZE;
+            }
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSARecv(IN SOCKET s,
+        IN OUT LPWSABUF lpBuffers,
+        IN DWORD dwBufferCount,
+        OUT LPDWORD lpNumberOfBytesRecvd,
+        IN OUT LPDWORD lpFlags,
+        IN LPWSAOVERLAPPED lpOverlapped,
+        IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    DPRINT("WSARecv: %lx, %lx, %lx, %p\n", s, lpFlags, dwBufferCount, lpBuffers);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPRecv(s,
+                                                         lpBuffers, 
+                                                         dwBufferCount,
+                                                         lpNumberOfBytesRecvd, 
+                                                         lpFlags, 
+                                                         lpOverlapped,
+                                                         lpCompletionRoutine, 
+                                                         ThreadId, 
+                                                         &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSARecvDisconnect(IN SOCKET s,
+                  OUT LPWSABUF lpInboundDisconnectData)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    INT ErrorCode;
+    INT Status;
+    DPRINT("WSARecvDisconnect: %lx %p\n", s, lpInboundDisconnectData);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPRecvDisconnect(s,
+                                                                   lpInboundDisconnectData,
+                                                                   &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSARecvFrom(IN SOCKET s,
+            IN OUT LPWSABUF lpBuffers,
+            IN DWORD dwBufferCount,
+            OUT LPDWORD lpNumberOfBytesRecvd,
+            IN OUT LPDWORD lpFlags,
+            OUT LPSOCKADDR lpFrom,
+            IN OUT LPINT lpFromlen,
+            IN LPWSAOVERLAPPED lpOverlapped,
+            IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    DPRINT("WSARecvFrom: %lx, %lx, %lx, %p\n", s, lpFlags, dwBufferCount, lpBuffers);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPRecvFrom(s,
+                                                             lpBuffers, 
+                                                             dwBufferCount,
+                                                             lpNumberOfBytesRecvd, 
+                                                             lpFlags, 
+                                                             lpFrom,
+                                                             lpFromlen,
+                                                             lpOverlapped,
+                                                             lpCompletionRoutine,
+                                                             ThreadId, 
+                                                             &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/rnr.c b/reactos/dll/win32/ws2_32_new/src/rnr.c
new file mode 100644 (file)
index 0000000..83f46e2
--- /dev/null
@@ -0,0 +1,814 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        rnr.c
+ * PURPOSE:     Registration n' Resolution Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAAddressToStringA(IN LPSOCKADDR lpsaAddress,
+                    IN DWORD dwAddressLength,
+                    IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
+                    OUT LPSTR lpszAddressString,
+                    IN OUT  LPDWORD lpdwAddressStringLength)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode, Status;
+    DWORD CatalogEntryId;
+    PTCATALOG Catalog;
+    PTCATALOG_ENTRY CatalogEntry;
+    LPWSTR UnicodeString;
+    DWORD Length = *lpdwAddressStringLength;
+    DPRINT("WSAAddressToStringA: %p\n", lpsaAddress);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Allocate the unicode string */
+    UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2);
+    if (!UnicodeString)
+    {
+        /* No memory; fail */
+        SetLastError(WSAENOBUFS);
+        return SOCKET_ERROR;
+    }
+
+    /* Get the catalog */
+    Catalog = WsProcGetTCatalog(Process);
+
+    /* Check if we got custom protocol info */
+    if (lpProtocolInfo)
+    {
+        /* Get the entry ID */
+        CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
+
+        /* Get the entry associated with it */
+        ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                   CatalogEntryId,
+                                                   &CatalogEntry);
+    }
+    else
+    {
+        /* Get it from the address family */
+        ErrorCode = WsTcGetEntryFromAf(Catalog,
+                                       lpsaAddress->sa_family,
+                                       &CatalogEntry);
+    }
+    
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Call the provider */
+        Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress,
+                                                                      dwAddressLength,
+                                                                      &CatalogEntry->
+                                                                      ProtocolInfo,
+                                                                      UnicodeString,
+                                                                      lpdwAddressStringLength,
+                                                                      &ErrorCode);
+        if (Status == ERROR_SUCCESS)
+        {
+            /* Convert the string */
+            WideCharToMultiByte(CP_ACP,
+                                0,
+                                UnicodeString,
+                                -1,
+                                lpszAddressString,
+                                Length,
+                                NULL,
+                                NULL);
+        }
+
+        /* Dereference the entry */
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Free the unicode string */
+        HeapFree(WsSockHeap, 0, UnicodeString);
+
+        /* Check for success and return */
+        if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+    }
+    else
+    {
+        /* Free the unicode string */
+        HeapFree(WsSockHeap, 0, UnicodeString);
+    }
+
+    /* Set the error and return */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAAddressToStringW(IN LPSOCKADDR lpsaAddress,
+                    IN DWORD dwAddressLength,
+                    IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
+                    OUT LPWSTR lpszAddressString,
+                    IN OUT LPDWORD lpdwAddressStringLength)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode, Status;
+    DWORD CatalogEntryId;
+    PTCATALOG Catalog;
+    PTCATALOG_ENTRY CatalogEntry;
+    DPRINT("WSAAddressToStringW: %p\n", lpsaAddress);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Get the catalog */
+    Catalog = WsProcGetTCatalog(Process);
+
+    /* Check if we got custom protocol info */
+    if (lpProtocolInfo)
+    {
+        /* Get the entry ID */
+        CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
+
+        /* Get the entry associated with it */
+        ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                   CatalogEntryId,
+                                                   &CatalogEntry);
+    }
+    else
+    {
+        /* Get it from the address family */
+        ErrorCode = WsTcGetEntryFromAf(Catalog,
+                                       lpsaAddress->sa_family,
+                                       &CatalogEntry);
+    }
+    
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Call the provider */
+        Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress,
+                                                                      dwAddressLength,
+                                                                      &CatalogEntry->
+                                                                      ProtocolInfo,
+                                                                      lpszAddressString,
+                                                                      lpdwAddressStringLength,
+                                                                      &ErrorCode);
+
+        /* Dereference the entry */
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Check for success and return */
+        if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+    }
+
+    /* Set the error and return */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSALookupServiceEnd(IN HANDLE hLookup)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PNSQUERY Query = hLookup;
+    DPRINT("WSALookupServiceEnd: %lx\n", hLookup);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Check for a valid handle, then validate and reference it */
+    if (!(Query) || !(WsNqValidateAndReference(Query)))
+    {
+        /* Fail */
+        SetLastError(WSA_INVALID_HANDLE);
+        return SOCKET_ERROR;
+    }
+
+    /* Do the lookup */
+    ErrorCode = WsNqLookupServiceEnd(Query);
+
+    /* Remove the validation reference */
+    WsNqDereference(Query);
+
+    /* Remove the keep-alive */
+    WsNqDereference(Query);
+
+    /* Return */
+    return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions,
+                       IN DWORD dwControlFlags,
+                       OUT LPHANDLE lphLookup)
+{
+    INT ErrorCode;
+    LPWSAQUERYSETW UnicodeQuerySet = NULL;
+    DWORD UnicodeQuerySetSize = 0;
+    DPRINT("WSALookupServiceBeginA: %p\n", lpqsRestrictions);
+
+    /* Verifiy pointer */
+    if (IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)))
+    {
+        /* Invalid */
+        SetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    /* Clear the reserved fields */
+    lpqsRestrictions->dwOutputFlags = 0;
+    lpqsRestrictions->lpszComment = NULL;
+    lpqsRestrictions->dwNumberOfCsAddrs = 0;
+
+    /* Find out the side we'll need */
+    ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions,
+                                         &UnicodeQuerySetSize,
+                                         UnicodeQuerySet);
+
+    /* We should've failed */
+    if (ErrorCode == WSAEFAULT)
+    {
+        /* Allocate the buffer we'll need */
+        UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize);
+        if (UnicodeQuerySet)
+        {
+            /* Do the conversion for real */
+            ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions,
+                                                 &UnicodeQuerySetSize,
+                                                 UnicodeQuerySet);
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* Now call the Unicode function */
+                ErrorCode = WSALookupServiceBeginW(UnicodeQuerySet,
+                                                   dwControlFlags,
+                                                   lphLookup);
+            }
+            else
+            {
+                /* Fail, conversion failed */
+                SetLastError(ErrorCode);
+            }
+
+            /* Free our buffer */
+            HeapFree(WsSockHeap, 0, UnicodeQuerySet);
+        }
+        else
+        {
+            /* No memory to allocate */
+            SetLastError(WSAEFAULT);
+        }
+    }
+    else
+    {
+        /* We couldn't get the size for some reason */
+        SetLastError(ErrorCode);
+    }
+
+    /* Return to caller */
+    return ErrorCode == ERROR_SUCCESS ? ErrorCode : SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT 
+WINAPI
+WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions,
+                       IN DWORD dwControlFlags,
+                       OUT LPHANDLE lphLookup)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PNSQUERY Query;
+    DPRINT("WSALookupServiceBeginW: %p\n", lpqsRestrictions);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Verify pointers */
+    if (IsBadWritePtr(lphLookup, sizeof(*lphLookup)) ||
+        IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)))
+    {
+        /* They are invalid; fail */
+        SetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    /* Create a new query object */
+    if ((Query = WsNqAllocate()))
+    {
+        /* Initialize it */
+        WsNqInitialize(Query);
+
+        /* Do the lookup */
+        ErrorCode = WsNqLookupServiceBegin(Query,
+                                           lpqsRestrictions,
+                                           dwControlFlags,
+                                           WsProcGetNsCatalog(Process));
+
+        /* Check for success */
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            /* Return the handle */
+            *lphLookup = Query;
+        }
+        else
+        {
+            /* Fail */
+            *lphLookup = NULL;
+            WsNqDelete(Query);
+        }
+    }
+    else
+    {
+        /* No memory */
+        ErrorCode = SOCKET_ERROR;
+        SetLastError(WSAENOBUFS);
+    }
+    
+    /* Return */
+    return ErrorCode;
+}
+
+/*
+ * @implemented
+ */
+INT
+WINAPI
+WSALookupServiceNextW(IN HANDLE hLookup,
+                      IN DWORD dwControlFlags,
+                      IN OUT LPDWORD lpdwBufferLength,
+                      OUT LPWSAQUERYSETW lpqsResults)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PNSQUERY Query = hLookup;
+    DPRINT("WSALookupServiceNextW: %lx\n", hLookup);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Check for a valid handle, then validate and reference it */
+    if (!(Query) || !(WsNqValidateAndReference(Query)))
+    {
+        /* Fail */
+        SetLastError(WSA_INVALID_HANDLE);
+        return SOCKET_ERROR;
+    }
+
+    /* Do the lookup */
+    ErrorCode = WsNqLookupServiceNext(Query,
+                                      dwControlFlags,
+                                      lpdwBufferLength,
+                                      lpqsResults);
+
+    /* Remove the validation reference */
+    WsNqDereference(Query);
+
+    /* Return */
+    return ErrorCode;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSALookupServiceNextA(IN HANDLE hLookup,
+                      IN DWORD dwControlFlags,
+                      IN OUT LPDWORD lpdwBufferLength,
+                      OUT LPWSAQUERYSETA lpqsResults)
+{
+    LPWSAQUERYSETW UnicodeQuerySet;
+    DWORD UnicodeQuerySetSize = *lpdwBufferLength;
+    INT ErrorCode;
+    DPRINT("WSALookupServiceNextA: %lx\n", hLookup);
+
+    /* Check how much the user is giving */
+    if (UnicodeQuerySetSize >= sizeof(WSAQUERYSETW))
+    {
+        /* Allocate the buffer we'll use */
+        UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize);
+        if (!UnicodeQuerySet) UnicodeQuerySetSize = 0;
+    }
+    else
+    {
+        /* His buffer is too small */
+        UnicodeQuerySetSize = 0;
+        UnicodeQuerySet = NULL;
+    }
+
+    /* Call the Unicode Function */
+    ErrorCode = WSALookupServiceNextW(hLookup,
+                                      dwControlFlags,
+                                      &UnicodeQuerySetSize,
+                                      UnicodeQuerySet);
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Not convert to ANSI */
+        ErrorCode = MapUnicodeQuerySetToAnsi(UnicodeQuerySet,
+                                             lpdwBufferLength,
+                                             lpqsResults);
+        if (ErrorCode != ERROR_SUCCESS) SetLastError(ErrorCode);
+    }
+    else
+    {
+        /* Check if we ran out of space */
+        if (GetLastError() == WSAEFAULT)
+        {
+            /* Return how much space we'll need, including padding */
+            *lpdwBufferLength = UnicodeQuerySetSize +
+                                ((sizeof(ULONG) * 6) - (6 * 1));
+        }
+    }
+
+    /* If we had a local buffer, free it */
+    if (UnicodeQuerySet) HeapFree(WsSockHeap, 0, UnicodeQuerySet);
+
+    /* Return to caller */
+    return ErrorCode == ERROR_SUCCESS ? ErrorCode : SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSANSPIoctl(HANDLE hLookup,
+            DWORD dwControlCode,
+            LPVOID lpvInBuffer,
+            DWORD cbInBuffer,
+            LPVOID lpvOutBuffer,
+            DWORD cbOutBuffer,
+            LPDWORD lpcbBytesReturned,
+            LPWSACOMPLETION lpCompletion)
+{
+    DPRINT("WSANSPIoctl: %lx\n", hLookup);
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSARemoveServiceClass(IN LPGUID lpServiceClassId)
+{
+    DPRINT("WSARemoveServiceClass: %lx\n", lpServiceClassId);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo,
+               IN WSAESETSERVICEOP essOperation,
+               IN DWORD dwControlFlags)
+{
+    DPRINT("WSASetServiceA: %lx\n", lpqsRegInfo);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo,
+               IN WSAESETSERVICEOP essOperation,
+               IN DWORD dwControlFlags)
+{
+    DPRINT("WSASetServiceW: %lx\n", lpqsRegInfo);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAGetServiceClassInfoA(IN LPGUID lpProviderId,
+                        IN LPGUID lpServiceClassId,
+                        IN OUT LPDWORD lpdwBufferLength,
+                        OUT LPWSASERVICECLASSINFOA lpServiceClassInfo)
+{
+    DPRINT("WSAGetServiceClassInfoA: %lx\n", lpProviderId);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAGetServiceClassInfoW(IN LPGUID lpProviderId,
+                        IN LPGUID lpServiceClassId,
+                        IN OUT LPDWORD lpdwBufferLength,
+                        OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+    DPRINT("WSAGetServiceClassInfoW: %lx\n", lpProviderId);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId,
+                                 OUT LPSTR lpszServiceClassName,
+                                 IN OUT LPDWORD lpdwBufferLength)
+{
+    DPRINT("WSAGetServiceClassNameByClassIdA: %lx\n", lpServiceClassId);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId,
+                                 OUT LPWSTR lpszServiceClassName,
+                                 IN OUT LPDWORD lpdwBufferLength)
+{
+    DPRINT("WSAGetServiceClassNameByClassIdW: %lx\n", lpServiceClassId);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo)
+{
+    DPRINT("WSAInstallServiceClassA: %lx\n", lpServiceClassInfo);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength,
+                           OUT LPWSANAMESPACE_INFOA lpnspBuffer)
+{
+    DPRINT("WSAEnumNameSpaceProvidersA: %lx\n", lpnspBuffer);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength,
+                           OUT LPWSANAMESPACE_INFOW lpnspBuffer)
+{
+    DPRINT("WSAEnumNameSpaceProvidersW: %lx\n", lpnspBuffer);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSAAPI
+WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+    DPRINT("WSAInstallServiceClassW: %lx\n", lpServiceClassInfo);
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAStringToAddressA(IN LPSTR AddressString,
+                    IN INT AddressFamily,
+                    IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
+                    OUT LPSOCKADDR lpAddress,
+                    IN OUT  LPINT lpAddressLength)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode, Status;
+    DWORD CatalogEntryId;
+    PTCATALOG Catalog;
+    PTCATALOG_ENTRY CatalogEntry;
+    LPWSTR UnicodeString;
+    DWORD Length = (DWORD)strlen(AddressString) + 1;
+    DPRINT("WSAStringToAddressA: %s\n", AddressString);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Allocate the unicode string */
+    UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2);
+    if (!UnicodeString)
+    {
+        /* No memory; fail */
+        SetLastError(WSAENOBUFS);
+        return SOCKET_ERROR;
+    }
+
+    /* Convert the string */
+    MultiByteToWideChar(CP_ACP, 0, AddressString, -1, UnicodeString, Length);
+
+    /* Get the catalog */
+    Catalog = WsProcGetTCatalog(Process);
+
+    /* Check if we got custom protocol info */
+    if (lpProtocolInfo)
+    {
+        /* Get the entry ID */
+        CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
+
+        /* Get the entry associated with it */
+        ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                   CatalogEntryId,
+                                                   &CatalogEntry);
+    }
+    else
+    {
+        /* Get it from the address family */
+        ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry);
+    }
+    
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Call the provider */
+        Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(UnicodeString,
+                                                              AddressFamily,
+                                                              &CatalogEntry->
+                                                              ProtocolInfo,
+                                                              lpAddress,
+                                                              lpAddressLength,
+                                                              &ErrorCode);
+
+        /* Dereference the entry */
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Free the unicode string */
+        HeapFree(WsSockHeap, 0, UnicodeString);
+
+        /* Check for success and return */
+        if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+    }
+    else
+    {
+        /* Free the unicode string */
+        HeapFree(WsSockHeap, 0, UnicodeString);
+    }
+
+    /* Set the error and return */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAStringToAddressW(IN LPWSTR AddressString,
+                    IN INT AddressFamily,
+                    IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
+                    OUT LPSOCKADDR lpAddress,
+                    IN OUT LPINT lpAddressLength)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode, Status;
+    DWORD CatalogEntryId;
+    PTCATALOG Catalog;
+    PTCATALOG_ENTRY CatalogEntry;
+    DPRINT("WSAStringToAddressW: %S\n", AddressString);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Leave now */
+        SetLastError(ErrorCode);
+        return SOCKET_ERROR;
+    }
+
+    /* Get the catalog */
+    Catalog = WsProcGetTCatalog(Process);
+
+    /* Check if we got custom protocol info */
+    if (lpProtocolInfo)
+    {
+        /* Get the entry ID */
+        CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
+
+        /* Get the entry associated with it */
+        ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                   CatalogEntryId,
+                                                   &CatalogEntry);
+    }
+    else
+    {
+        /* Get it from the address family */
+        ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry);
+    }
+    
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Call the provider */
+        Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(AddressString,
+                                                                      AddressFamily,
+                                                                      &CatalogEntry->
+                                                                      ProtocolInfo,
+                                                                      lpAddress,
+                                                                      lpAddressLength,
+                                                                      &ErrorCode);
+
+        /* Dereference the entry */
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Check for success and return */
+        if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+    }
+
+    /* Set the error and return */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/scihlpr.c b/reactos/dll/win32/ws2_32_new/src/scihlpr.c
new file mode 100644 (file)
index 0000000..c7f7bde
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        scihlpr.c
+ * PURPOSE:     Service Class Information Conversion/Packing Helpers
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
diff --git a/reactos/dll/win32/ws2_32_new/src/select.c b/reactos/dll/win32/ws2_32_new/src/select.c
new file mode 100644 (file)
index 0000000..22b9a72
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        sselect.c
+ * PURPOSE:     Socket Select Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSPAPI
+__WSAFDIsSet(SOCKET s,
+             LPFD_SET set)
+{
+    INT i = set->fd_count;
+    INT Return = FALSE;
+
+    /* Loop until a match is found */
+    while (i--) if (set->fd_array[i] == s) Return = TRUE;
+
+    /* Return */
+    return Return;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+select(IN INT s, 
+       IN OUT LPFD_SET readfds, 
+       IN OUT LPFD_SET writefds, 
+       IN OUT LPFD_SET exceptfds, 
+       IN CONST struct timeval *timeout)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    BOOL Found = FALSE;
+    SOCKET Handle;
+    DPRINT("select: %lx %p %p %p %p\n", s, readfds, writefds, exceptfds, timeout);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Use the first Socket from the first valid set */
+        if (readfds && readfds->fd_count) 
+        {
+            Handle = readfds->fd_array[0];
+            Found = TRUE;
+        } 
+        if (!Found && writefds && writefds->fd_count) 
+        {
+            Handle = writefds->fd_array[0];
+            Found = TRUE;
+        } 
+        if (!Found && exceptfds && exceptfds->fd_count) 
+        {
+            Handle = exceptfds->fd_array[0];
+            Found = TRUE;
+        }
+
+        /* Make sure we found one */
+        if (Found)
+        {
+            /* Get the Socket Context */
+            if ((Socket = WsSockGetSocket(Handle)))
+            {
+                /* Make the call */
+                Status = Socket->Provider->Service.lpWSPSelect(s,
+                                                               readfds, 
+                                                               writefds,
+                                                               exceptfds, 
+                                                               timeout, 
+                                                               &ErrorCode);
+                /* Deference the Socket Context */
+                WsSockDereference(Socket);
+
+                /* Return Provider Value */
+                if (Status != SOCKET_ERROR) return Status;
+
+                /* If everything seemed fine, then the WSP call failed itself */
+                if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+            }
+            else
+            {
+                /* No Socket Context Found */
+                ErrorCode = WSAENOTSOCK;
+            }
+        }
+        else
+        {
+            /* Invalid handles */
+            ErrorCode = WSAEINVAL;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUFDIsSet(IN SOCKET s,
+           IN LPFD_SET set)
+{
+    UNIMPLEMENTED;
+    return (SOCKET)0;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAAsyncSelect(IN SOCKET s,
+               IN HWND hWnd,
+               IN UINT wMsg,
+               IN LONG lEvent)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSAAsyncSelect: %lx, %lx, %lx, %lx\n", s, hWnd, wMsg, lEvent);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPAsyncSelect(s,
+                                                                hWnd, 
+                                                                wMsg,
+                                                                lEvent, 
+                                                                &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAEventSelect(IN SOCKET s,
+               IN WSAEVENT hEventObject,
+               IN LONG lNetworkEvents)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPEventSelect(s,
+                                                        hEventObject,
+                                                        lNetworkEvents,
+                                                        &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/send.c b/reactos/dll/win32/ws2_32_new/src/send.c
new file mode 100644 (file)
index 0000000..8201925
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        send.c
+ * PURPOSE:     Socket Sending Support.
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+send(IN SOCKET s, 
+     IN CONST CHAR FAR* buf, 
+     IN INT len, 
+     IN INT flags)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    WSABUF Buffers;
+    DWORD BytesSent;
+    DPRINT("send: %lx, %lx, %lx, %p\n", s, flags, len, buf);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Setup the buffers */
+            Buffers.buf = (PCHAR)buf;
+            Buffers.len = len;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSend(s,
+                                                         &Buffers, 
+                                                         1,
+                                                         &BytesSent, 
+                                                         (DWORD)flags, 
+                                                         NULL,
+                                                         NULL, 
+                                                         ThreadId, 
+                                                         &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return BytesSent;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+sendto(IN SOCKET s,
+       IN CONST CHAR FAR* buf,
+       IN INT len,
+       IN INT flags,
+       IN CONST struct sockaddr *to, 
+       IN INT tolen)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    WSABUF Buffers;
+    DWORD BytesSent;
+    DPRINT("send: %lx, %lx, %lx, %p\n", s, flags, len, buf);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Setup the buffers */
+            Buffers.buf = (PCHAR)buf;
+            Buffers.len = len;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSendTo(s,
+                                                           &Buffers, 
+                                                           1,
+                                                           &BytesSent, 
+                                                           (DWORD)flags,
+                                                           to,
+                                                           tolen,
+                                                           NULL,
+                                                           NULL, 
+                                                           ThreadId, 
+                                                           &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return BytesSent;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSASend(IN SOCKET s,
+        IN LPWSABUF lpBuffers,
+        IN DWORD dwBufferCount,
+        OUT LPDWORD lpNumberOfBytesSent,
+        IN DWORD dwFlags,
+        IN LPWSAOVERLAPPED lpOverlapped,
+        IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    DPRINT("WSARecvFrom: %lx, %lx, %lx, %p\n", s, dwFlags, dwBufferCount, lpBuffers);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSend(s,
+                                                         lpBuffers, 
+                                                         dwBufferCount,
+                                                         lpNumberOfBytesSent, 
+                                                         dwFlags, 
+                                                         lpOverlapped,
+                                                         lpCompletionRoutine, 
+                                                         ThreadId, 
+                                                         &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSASendDisconnect(IN SOCKET s,
+                  IN LPWSABUF lpOutboundDisconnectData)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    INT ErrorCode;
+    INT Status;
+    DPRINT("WSASendDisconnect: %lx %p\n", s, lpOutboundDisconnectData);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSendDisconnect(s,
+                                                                   lpOutboundDisconnectData,
+                                                                   &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSASendTo(IN SOCKET s,
+          IN LPWSABUF lpBuffers,
+          IN DWORD dwBufferCount,
+          OUT LPDWORD lpNumberOfBytesSent,
+          IN DWORD dwFlags,
+          IN CONST struct sockaddr *lpTo,
+          IN INT iToLen,
+          IN LPWSAOVERLAPPED lpOverlapped,
+          IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    LPWSATHREADID ThreadId;
+    DPRINT("WSASendTo: %lx, %lx, %lx, %p\n", s, dwFlags, dwBufferCount, lpBuffers);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickPrologTid(&ThreadId)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSendTo(s,
+                                                           lpBuffers, 
+                                                           dwBufferCount,
+                                                           lpNumberOfBytesSent, 
+                                                           dwFlags, 
+                                                           lpTo,
+                                                           iToLen,
+                                                           lpOverlapped,
+                                                           lpCompletionRoutine, 
+                                                           ThreadId, 
+                                                           &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/sockctrl.c b/reactos/dll/win32/ws2_32_new/src/sockctrl.c
new file mode 100644 (file)
index 0000000..b87b334
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        socktrl.c
+ * PURPOSE:     Socket Control/State Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+connect(IN SOCKET s,
+        IN CONST struct sockaddr *name,
+        IN INT namelen)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    INT ErrorCode, OldErrorCode;
+    INT Status;
+    BOOLEAN TryAgain = TRUE;
+    DPRINT("connect: %lx, %p, %lx\n", s, name, namelen);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            while (TRUE)
+            {
+                /* Make the call */
+                Status = Socket->Provider->Service.lpWSPConnect(s,
+                                                                name,
+                                                                namelen,
+                                                                NULL,
+                                                                NULL,
+                                                                NULL,
+                                                                NULL,
+                                                                &ErrorCode);
+
+                /* Check if error code was due to the host not being found */
+                if ((Status == SOCKET_ERROR) &&
+                    (ErrorCode == WSAEHOSTUNREACH) &&
+                    (ErrorCode == WSAENETUNREACH))
+                {
+                    /* Check if we can try again */
+                    if (TryAgain)
+                    {
+                        /* Save the old error code */
+                        OldErrorCode = ErrorCode;
+
+                        /* Make sure we don't retry 3 times */
+                        TryAgain = FALSE;
+
+                        /* Make the RAS Auto-dial attempt */
+                        if (WSAttemptAutodialAddr(name, namelen)) continue;
+                    }
+                    else
+                    {
+                        /* Restore the error code */
+                        ErrorCode = OldErrorCode;
+                    }
+                }
+
+                /* Break out of the loop */
+                break;
+            }
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* If this is Winsock 1.1, normalize the error code */
+    if ((ErrorCode == WSAEALREADY) && (LOBYTE(Process->Version) == 1))
+    {
+        /* WS 1.1 apps expect this */
+        ErrorCode = WSAEINVAL;
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+listen(IN SOCKET s,
+       IN INT backlog)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("connect: %lx, %lx\n", s, backlog);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPListen(s,
+                                                           backlog,
+                                                           &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+getpeername(IN SOCKET s,
+            OUT LPSOCKADDR name,
+            IN OUT INT FAR* namelen)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("getpeername: %lx, %p, %lx\n", s, name, namelen);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPGetPeerName(s,
+                                                                name,
+                                                                namelen,
+                                                                &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+getsockname(IN SOCKET s,
+            OUT LPSOCKADDR name,
+            IN OUT INT FAR* namelen)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("getsockname: %lx, %p, %lx\n", s, name, namelen);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPGetSockName(s,
+                                                                name,
+                                                                namelen,
+                                                                &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+getsockopt(IN SOCKET s,
+           IN INT level,
+           IN INT optname,
+           OUT CHAR FAR* optval,
+           IN OUT INT FAR* optlen)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    INT ErrorCode;
+    INT Status;
+    WSAPROTOCOL_INFOW ProtocolInfo;
+    PCHAR OldOptVal = NULL;
+    INT OldOptLen = 0;
+    DPRINT("getsockopt: %lx, %lx, %lx\n", s, level, optname);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Check if we're getting the open type */
+        if ((level == SOL_SOCKET) && (optname == SO_OPENTYPE))
+        {
+            /* Validate size */
+            if (!(optlen) || (*optlen < sizeof(INT)))
+            {
+                /* Fail */
+                SetLastError(WSAEFAULT);
+                return SOCKET_ERROR;
+            }
+
+            /* Set the open type */
+            *optval = (CHAR)Thread->OpenType;
+            *optlen = sizeof(INT);
+            return ERROR_SUCCESS;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Check if ANSI data was requested */
+            if ((level == SOL_SOCKET) && (optname == SO_PROTOCOL_INFOA))
+            {
+                /* Validate size and pointers */
+                if(!(optval) ||
+                   !(optlen) ||
+                   (*optlen < sizeof(WSAPROTOCOL_INFOA)))
+                {
+                    /* Set return size */
+                    *optlen = sizeof(WSAPROTOCOL_INFOA);
+
+                    /* Dereference the socket and fail */
+                    WsSockDereference(Socket);
+                    SetLastError(WSAEFAULT);
+                    return SOCKET_ERROR;
+                }
+
+                /* It worked. Save the values */
+                OldOptLen = *optlen;
+                OldOptVal = optval;
+
+                /* Hack them so WSP will know how to deal with it */
+                *optlen = sizeof(WSAPROTOCOL_INFOW);
+                optval = (PCHAR)&ProtocolInfo;
+                optname = SO_PROTOCOL_INFOW;
+            }
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPGetSockOpt(s,
+                                                               level,
+                                                               optname,
+                                                               optval,
+                                                               optlen,
+                                                               &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Check provider value */
+            if (Status == ERROR_SUCCESS)
+            {
+                /* Did we use the A->W hack? */
+                if (!OldOptVal) return Status;
+
+                /* We did, so we have to convert the unicode info to ansi */
+                ErrorCode = MapUnicodeProtocolInfoToAnsi(&ProtocolInfo,
+                                                         (LPWSAPROTOCOL_INFOA)
+                                                         OldOptVal);
+
+                /* Return the length */
+                *optlen = OldOptLen;
+
+                /* Return success if this worked */
+                if (ErrorCode == ERROR_SUCCESS) return Status;
+            }
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+setsockopt(IN SOCKET s,
+           IN INT level,
+           IN INT optname,
+           IN CONST CHAR FAR* optval,
+           IN INT optlen)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    INT ErrorCode;
+    INT Status;
+    DPRINT("setsockopt: %lx, %lx, %lx\n", s, level, optname);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Check if we're changing the open type */
+        if (level == SOL_SOCKET && optname == SO_OPENTYPE)
+        {
+            /* Validate size */
+            if (optlen < sizeof(INT))
+            {
+                /* Fail */
+                SetLastError(WSAEFAULT);
+                return SOCKET_ERROR;
+            }
+
+            /* Set the open type */
+            Thread->OpenType = *optval;
+            return ERROR_SUCCESS;
+        }
+
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPSetSockOpt(s,
+                                                               level,
+                                                               optname,
+                                                               optval,
+                                                               optlen,
+                                                               &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+shutdown(IN SOCKET s,
+         IN INT how)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("shutdown: %lx, %lx\n", s, how);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPShutdown(s, how, &ErrorCode);
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSAConnect(IN SOCKET s,
+           IN CONST struct sockaddr *name,
+           IN INT namelen,
+           IN LPWSABUF lpCallerData,
+           OUT LPWSABUF lpCalleeData,
+           IN LPQOS lpSQOS,
+           IN LPQOS lpGQOS)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSAConnect: %lx, %lx, %lx, %p\n", s, name, namelen, lpCallerData);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPConnect(s,
+                                                            name,
+                                                            namelen,
+                                                            lpCallerData,
+                                                            lpCalleeData,
+                                                            lpSQOS,
+                                                            lpGQOS,
+                                                            &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WSAAPI
+WSAGetOverlappedResult(IN SOCKET s,
+                       IN LPWSAOVERLAPPED lpOverlapped,
+                       OUT LPDWORD lpcbTransfer,
+                       IN BOOL fWait,
+                       OUT LPDWORD lpdwFlags)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("WSAGetOverlappedResult: %lx, %lx\n", s, lpOverlapped);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPGetOverlappedResult(s,
+                                                                        lpOverlapped,
+                                                                        lpcbTransfer,
+                                                                        fWait,
+                                                                        lpdwFlags,
+                                                                        &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status) return Status;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return FALSE;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/socklife.c b/reactos/dll/win32/ws2_32_new/src/socklife.c
new file mode 100644 (file)
index 0000000..5d8dc80
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        socklife.c
+ * PURPOSE:     Socket Lifetime Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI
+accept(IN  SOCKET s,
+       OUT LPSOCKADDR addr,
+       OUT INT FAR* addrlen)
+{
+    /* Let WSA do it */
+    return WSAAccept(s, addr, addrlen, NULL, 0);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+bind(IN SOCKET s,
+     IN CONST struct sockaddr *name,
+     IN INT namelen)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("bind: %lx, %p, %lx\n", s, name, namelen);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPBind(s,
+                                                         name, 
+                                                         namelen,
+                                                         &ErrorCode);
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Return Provider Value */
+            if (Status == ERROR_SUCCESS) return Status;
+
+            /* If everything seemed fine, then the WSP call failed itself */
+            if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+closesocket(IN SOCKET s)
+{
+    PWSSOCKET Socket;
+    INT Status;
+    INT ErrorCode;
+    DPRINT("closesocket: %lx\n", s);
+
+    /* Check for WSAStartup */
+    if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPCloseSocket(s, &ErrorCode);
+
+            /* Check if this is a provider socket */
+            if ((Status == ERROR_SUCCESS) && (Socket->IsProvider))
+            {
+                /* Disassociate the handle */
+                if (WsSockDisassociateHandle(Socket) == ERROR_SUCCESS)
+                {
+                    /* Deference the Socket Context */
+                    WsSockDereference(Socket);
+                }
+
+                /* Remove the last reference */
+                WsSockDereference(Socket);
+
+                /* Return success if everything is OK */
+                if (ErrorCode == ERROR_SUCCESS) return ErrorCode;
+            }
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI
+socket(IN INT af,
+       IN INT type,
+       IN INT protocol)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    DWORD Flags = 0;
+    INT ErrorCode;
+    DPRINT("socket: %lx, %lx, %lx\n", af, type, protocol);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Fail here */
+        SetLastError(ErrorCode);
+        return INVALID_SOCKET;
+    }
+
+    /* Check the current open type and use overlapped if it's default */
+    if (!Thread->OpenType) Flags = WSA_FLAG_OVERLAPPED;
+
+    /* Make the protocol negative if this is NETBIOS */
+    if ((af == AF_NETBIOS) && (protocol > 0)) protocol *= -1;
+
+    /* Now let WSA handle it */
+    return WSASocketW(af, type, protocol, NULL, 0, Flags);
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUCloseSocketHandle(IN SOCKET s,
+                     OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+SOCKET
+WSPAPI
+WPUCreateSocketHandle(IN DWORD dwCatalogEntryId,
+                      IN DWORD dwContext,
+                      OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return (SOCKET)0;
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSPAPI
+WPUModifyIFSHandle(IN DWORD dwCatalogEntryId,
+                   IN SOCKET ProposedHandle,
+                   OUT LPINT lpErrno)
+{
+    SOCKET Handle = INVALID_SOCKET;
+    DWORD ErrorCode = ERROR_SUCCESS;
+    PWSPROCESS Process;
+    PTCATALOG Catalog;
+    PTCATALOG_ENTRY Entry;
+    PWSSOCKET Socket;
+    DPRINT("WPUModifyIFSHandle: %lx, %lx\n", dwCatalogEntryId, ProposedHandle);
+
+    /* Get the current process */
+    if ((Process = WsGetProcess()))
+    {
+        /* Get the Transport Catalog */
+        if ((Catalog = WsProcGetTCatalog(Process)))
+        {
+            /* Get the entry for this ID */
+            ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                       dwCatalogEntryId,
+                                                       &Entry);
+            /* Check for success */
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* Create a socket object */
+                if ((Socket = WsSockAllocate()))
+                {
+                    /* Initialize it */
+                    WsSockInitialize(Socket, Entry);
+
+                    /* Associate it */
+                    ErrorCode = WsSockAssociateHandle(Socket,
+                                                      ProposedHandle,
+                                                      TRUE);
+                    /* Check for success */
+                    if (ErrorCode == ERROR_SUCCESS)
+                    {
+                        /* Return */
+                        Handle = ProposedHandle;
+                        *lpErrno = ERROR_SUCCESS;
+                    }
+                    else
+                    {
+                        /* Fail */
+                        WsSockDereference(Socket);
+                        *lpErrno = ErrorCode;
+                    }
+
+                    /* Dereference the extra count */
+                    WsSockDereference(Socket);
+                }
+                else
+                {
+                    /* No memory to allocate a socket */
+                    *lpErrno = WSAENOBUFS;
+                }
+
+                /* Dereference the catalog entry */
+                WsTcEntryDereference(Entry);
+            }
+            else
+            {
+                /* Entry not found */
+                *lpErrno = ErrorCode;
+            }
+        }
+        else
+        {
+            /* Catalog not found */
+            *lpErrno = WSANOTINITIALISED;
+        }
+    }
+    else
+    {
+        /* Process not ready */
+        *lpErrno = WSANOTINITIALISED;
+    }
+
+    /* Return */
+    return Handle;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUQuerySocketHandleContext(IN SOCKET s,
+                            OUT LPDWORD lpContext,
+                            OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI
+WSAAccept(IN SOCKET s,
+          OUT LPSOCKADDR addr,
+          IN OUT LPINT addrlen,
+          IN LPCONDITIONPROC lpfnCondition,
+          IN DWORD dwCallbackData)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    DWORD OpenType;
+    INT ErrorCode;
+    SOCKET Status;
+    DPRINT("WSAAccept: %lx, %lx, %lx, %p\n", s, addr, addrlen, lpfnCondition);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Get the old open type and set new one */
+            OpenType = Thread->OpenType;
+            Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPAccept(s,
+                                                           addr,
+                                                           addrlen,
+                                                           lpfnCondition,
+                                                           dwCallbackData,
+                                                           &ErrorCode);
+            /* Restore open type */
+            Thread->OpenType = OpenType;
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Check if we got a valid socket */
+            if (Status != INVALID_SOCKET)
+            {
+                /* Check if we got a new socket */
+                if (Status != s)
+                {
+                    /* Add a new reference */
+                    WsSockAddApiReference(Status);
+                }
+
+                /* Return */
+                return Status;
+            }
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return INVALID_SOCKET;
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI
+WSAJoinLeaf(IN SOCKET s,
+            IN CONST struct sockaddr *name,
+            IN INT namelen,
+            IN LPWSABUF lpCallerData,
+            OUT LPWSABUF lpCalleeData,
+            IN LPQOS lpSQOS,
+            IN LPQOS lpGQOS,
+            IN DWORD dwFlags)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PWSSOCKET Socket;
+    DWORD OpenType;
+    INT ErrorCode;
+    SOCKET Status;
+    DPRINT("WSAJoinLeaf: %lx, %lx, %lx\n", s, name, namelen);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the Socket Context */
+        if ((Socket = WsSockGetSocket(s)))
+        {
+            /* Get the old open type and set new one */
+            OpenType = Thread->OpenType;
+            Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT;
+
+            /* Make the call */
+            Status = Socket->Provider->Service.lpWSPJoinLeaf(s,
+                                                             name,
+                                                             namelen,
+                                                             lpCallerData,
+                                                             lpCalleeData,
+                                                             lpSQOS,
+                                                             lpGQOS,
+                                                             dwFlags,
+                                                             &ErrorCode);
+            /* Restore open type */
+            Thread->OpenType = OpenType;
+
+            /* Deference the Socket Context */
+            WsSockDereference(Socket);
+
+            /* Check if we got a valid socket */
+            if (Status != INVALID_SOCKET)
+            {
+                /* Check if we got a new socket */
+                if (Status != s)
+                {
+                    /* Add a new reference */
+                    WsSockAddApiReference(Status);
+                }
+
+                /* Return */
+                return Status;
+            }
+        }
+        else
+        {
+            /* No Socket Context Found */
+            ErrorCode = WSAENOTSOCK;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return INVALID_SOCKET;
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI
+WSASocketA(IN INT af,
+           IN INT type,
+           IN INT protocol,
+           IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
+           IN GROUP g,
+           IN DWORD dwFlags)
+{
+    WSAPROTOCOL_INFOW ProtocolInfoW;
+    LPWSAPROTOCOL_INFOW p = &ProtocolInfoW;
+
+    /* Convert Protocol Info to Wide */
+    if (lpProtocolInfo) 
+    {    
+        /* Copy the Data */
+        memcpy(&ProtocolInfoW,
+               lpProtocolInfo,
+               sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
+
+        /* Convert the String */
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            lpProtocolInfo->szProtocol,
+                            -1,
+                            ProtocolInfoW.szProtocol,
+                            sizeof(ProtocolInfoW.szProtocol) / sizeof(WCHAR));
+    } 
+    else 
+    {
+        /* No Protocol Info Specified */
+        p = NULL;
+    }
+
+    /* Call the Unicode Function */
+    return WSASocketW(af,
+                      type,
+                      protocol,
+                      p,
+                      g,
+                      dwFlags);
+}
+
+/*
+ * @implemented
+ */
+SOCKET
+WSAAPI 
+WSASocketW(IN INT af,
+           IN INT type,
+           IN INT protocol,
+           IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
+           IN GROUP g,
+           IN DWORD dwFlags)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    PTCATALOG Catalog;
+    DWORD CatalogId;
+    PTCATALOG_ENTRY CatalogEntry;
+    LPWSAPROTOCOL_INFOW ProtocolInfo;
+    DWORD OpenType;
+    SOCKET Status = INVALID_SOCKET;
+    DPRINT("WSASocketW: %lx, %lx, %lx, %p\n", af, type, protocol, lpProtocolInfo);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* Fail now */
+        SetLastError(ErrorCode);
+        return INVALID_SOCKET;
+    }
+
+    /* Get the catalog */
+    Catalog = WsProcGetTCatalog(Process);
+
+    /* Find a Provider for the Catalog ID */
+    if (lpProtocolInfo) 
+    {   
+        /* Get the catalog ID */
+        CatalogId = lpProtocolInfo->dwCatalogEntryId;
+
+        /* Get the Catalog Entry */
+        ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                   CatalogId,
+                                                   &CatalogEntry);
+    }
+    else  
+    {   
+        /* No ID */
+        CatalogId = 0;
+
+DoLookup:
+        /* Get the Catalog Data from the Socket Info */
+        ErrorCode = WsTcGetEntryFromTriplet(Catalog,
+                                            af,
+                                            type,
+                                            protocol,
+                                            CatalogId,
+                                            &CatalogEntry);
+    }
+
+    /* Check for Success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Use the default Protocol Info if none given */
+        ProtocolInfo = lpProtocolInfo ? lpProtocolInfo : &CatalogEntry->ProtocolInfo;
+
+        /* Save the open type and set new one */
+        OpenType = Thread->OpenType;
+        Thread->OpenType = (dwFlags & WSA_FLAG_OVERLAPPED) ?
+                            0 : SO_SYNCHRONOUS_NONALERT;
+
+        /* Call the Provider to create the Socket */
+        Status = CatalogEntry->Provider->Service.lpWSPSocket(af,
+                                                             type,
+                                                             protocol,
+                                                             ProtocolInfo,
+                                                             g,
+                                                             dwFlags,
+                                                             &ErrorCode);
+        /* Restore open type */
+        Thread->OpenType = OpenType;
+
+        /* Get the catalog ID now, and dereference */
+        CatalogId = ProtocolInfo->dwCatalogEntryId;
+        WsTcEntryDereference(CatalogEntry);
+
+        /* Did we fail with WSAEINPROGRESS and had no specific provider? */
+        if ((Status == INVALID_SOCKET) && 
+            (ErrorCode == WSAEINPROGRESS) && 
+            !(lpProtocolInfo))
+        {
+            /* In that case, restart the lookup from this ID */
+            goto DoLookup;
+        }
+
+        /* Check if we got a valid socket */
+        if (Status != INVALID_SOCKET)
+        {
+            /* Add an API reference and return */
+            WsSockAddApiReference(Status);
+            return Status;
+        }
+    }
+
+    /* Return with an Error */
+    SetLastError(ErrorCode);
+    return INVALID_SOCKET;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/spinstal.c b/reactos/dll/win32/ws2_32_new/src/spinstal.c
new file mode 100644 (file)
index 0000000..53a8031
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        spinstal.c
+ * PURPOSE:     Transport Service Provider Installation
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCInstallProvider(IN LPGUID lpProviderId,
+                   IN CONST WCHAR * lpszProviderDllPath,
+                   IN CONST LPWSAPROTOCOL_INFOW lpProtocolInfoList,
+                   IN DWORD dwNumberOfEntries,
+                   OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCDeinstallProvider(IN LPGUID lpProviderId,
+                     OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WSCWriteProviderOrder(IN LPDWORD lpwdCatalogEntryId,
+                      IN DWORD dwNumberOfEntries)
+{
+    UNIMPLEMENTED;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/sputil.c b/reactos/dll/win32/ws2_32_new/src/sputil.c
new file mode 100644 (file)
index 0000000..e82922a
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        sputil.c
+ * PURPOSE:     Transport Service Provider Utility Functions
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUCompleteOverlappedRequest(IN SOCKET s,
+                             IN LPWSAOVERLAPPED lpOverlapped,
+                             IN DWORD dwError,
+                             IN DWORD cbTransferred,
+                             OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WSPAPI
+WPUCloseEvent(IN WSAEVENT hEvent,
+              OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUCloseThread(IN LPWSATHREADID lpThreadId,
+               OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+WSAEVENT
+WSPAPI
+WPUCreateEvent(OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return (WSAEVENT)0;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUOpenCurrentThread(OUT LPWSATHREADID lpThreadId,
+                     OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WSPAPI
+WPUPostMessage(IN HWND hWnd,
+               IN UINT Msg,
+               IN WPARAM wParam,
+               IN LPARAM lParam)
+{
+    /* Make sure we have a post routine */
+    if (!WsSockPostRoutine) WsSockPostRoutine = PostMessage;
+
+    /* Call it */
+    return WsSockPostRoutine(hWnd, Msg, wParam, lParam);
+}
+
+/*
+ * @implemented
+ */
+INT
+WSPAPI
+WPUQueryBlockingCallback(IN DWORD dwCatalogEntryId,
+                         OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback,
+                         OUT PDWORD_PTR lpdwContext,
+                         OUT LPINT lpErrno)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    PTCATALOG Catalog;
+    INT ErrorCode;
+    INT Status;
+    LPBLOCKINGCALLBACK Callback = NULL;
+    PTCATALOG_ENTRY Entry;
+    DWORD_PTR Context = 0;
+    DPRINT("WPUQueryBlockingCallback: %lx \n", dwCatalogEntryId);
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Get the callback function */
+        Callback = Thread->BlockingCallback;
+
+        /* Check if there is one */
+        if (Callback)
+        {
+            /* Get the catalog */
+            Catalog = WsProcGetTCatalog(Process);
+
+            /* Find the entry for this ID */
+            ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
+                                                       dwCatalogEntryId,
+                                                       &Entry);
+
+            /* Check for success */
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* Get the context */
+                Context = (DWORD_PTR)Entry->Provider->Service.lpWSPCancelBlockingCall;
+
+                /* Dereference the entry */
+                WsTcEntryDereference(Entry);
+            }
+        }
+    }
+
+    /* Check error code */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Return success as well */
+        Status = ERROR_SUCCESS;
+    }
+    else
+    {
+        /* Return excpected value and no callback */
+        Status = SOCKET_ERROR;
+        Callback = NULL;
+    }
+
+    /* Return the settings */
+    *lpdwContext = Context;
+    *lpErrno = ErrorCode;
+    *lplpfnCallback = Callback;
+
+    /* Return to caller */
+    return Status;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WSPAPI
+WPUQueueApc(IN LPWSATHREADID lpThreadId,
+            IN LPWSAUSERAPC lpfnUserApc,
+            IN DWORD dwContext,
+            OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WSPAPI
+WPUResetEvent(IN WSAEVENT hEvent,
+              OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WSPAPI
+WPUSetEvent(IN WSAEVENT hEvent,
+            OUT LPINT lpErrno)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/startup.c b/reactos/dll/win32/ws2_32_new/src/startup.c
new file mode 100644 (file)
index 0000000..58a764f
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        startup.c
+ * PURPOSE:     Startup/Cleanup Support
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+PWS_SOCK_POST_ROUTINE WsSockPostRoutine = NULL;
+CRITICAL_SECTION WsStartupLock;
+
+#define WsStartupLock()          EnterCriticalSection(&WsStartupLock);
+#define WsStartupUnlock()        LeaveCriticalSection(&WsStartupLock);
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WSAAPI
+WsCreateStartupSynchronization(VOID)
+{
+    /* Initialize the startup lock */
+    InitializeCriticalSection(&WsStartupLock);
+}
+
+VOID
+WSAAPI
+WsDestroyStartupSynchronization(VOID)
+{
+    /* Destroy the startup lock */
+    DeleteCriticalSection(&WsStartupLock);
+}
+
+/*
+ * @implemented
+ */
+BOOL 
+WSAAPI 
+WSApSetPostRoutine(PVOID Routine)
+{
+    /* Set the post routine */
+    DPRINT("WSApSetPostRoutine: %p\n", Routine);
+    WsSockPostRoutine = (PWS_SOCK_POST_ROUTINE)Routine;
+    return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+INT
+WSAAPI
+WSACleanup(VOID)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+    LONG RefCount;
+    DPRINT("WSACleanup\n");
+
+    /* Enter startup lock */
+    WsStartupLock();
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
+    {
+        /* Decrement process reference count and check if it's zero */
+        if (!(RefCount = InterlockedDecrement(&Process->RefCount)))
+        {
+            /* It's zero, destroy the process structure */
+            WsProcDelete(Process);
+        }
+        else if (RefCount == 1 && WsAsyncThreadInitialized)
+        {
+            /* Kill async thread */
+            WsAsyncTerminateThread();
+        }
+
+        /* Return success */
+        ErrorCode = ERROR_SUCCESS;
+    }
+    else
+    {
+        /* Weren't initialized */
+        SetLastError(ErrorCode);
+        ErrorCode = SOCKET_ERROR;
+    }
+
+    /* Release startup lock */
+    WsStartupUnlock();
+
+    /* Done */
+    return ErrorCode;
+}
+
+/*
+ * @implemented
+ */
+INT
+WINAPI
+WSAStartup(IN WORD wVersionRequested,
+           OUT LPWSADATA lpWSAData)
+{
+    WORD VersionReturned = 0;
+    DWORD ErrorCode = ERROR_SUCCESS;
+    PWSPROCESS CurrentProcess;
+    DPRINT("WSAStartup: %wx\n", wVersionRequested);
+
+    /* Make sure that we went through DLL Init */
+    if (!WsDllHandle) return WSASYSNOTREADY;
+
+    /* Check which version is being requested */
+    switch (LOBYTE(wVersionRequested))
+    {
+        case 0:
+
+            /* We don't support this unknown version */
+            ErrorCode = WSAVERNOTSUPPORTED;
+            break;
+
+        case 1:
+            /* We support only 1.0 and 1.1 */
+            if (HIBYTE(wVersionRequested) == 0)
+            {
+                /* Caller wants 1.0, return it */
+                VersionReturned = wVersionRequested;
+            }
+            else
+            {
+                /* The only other version we support is 1.1 */
+                VersionReturned = MAKEWORD(1, 1);
+            }
+            break;
+
+        case 2:
+            /* We support only 2.0, 2.1 and 2.2 */
+            if (HIBYTE(wVersionRequested) <= 2)
+            {
+                /* Caller wants 2.0-2.2, return it */
+                VersionReturned = MAKEWORD(2, HIBYTE(wVersionRequested));
+            }
+            else
+            {
+                /* The highest version we support is 2.2 */
+                VersionReturned = MAKEWORD(2, 2);
+            }
+            break;
+
+        default:
+
+            /* Return 2.2 */
+            VersionReturned = MAKEWORD(2, 2);;
+            break;
+    }
+
+    /* Return the Version Requsted, unless error */
+    lpWSAData->wVersion = VersionReturned;
+
+    /* We support Winsock 2.2 */
+    lpWSAData->wHighVersion = MAKEWORD(2,2);
+    lstrcpy(lpWSAData->szDescription, "WinSock 2.2");
+    lstrcpy(lpWSAData->szSystemStatus, "Running");
+
+    /* 
+     * On Winsock 1, the following values are returned.
+     * Taken straight from a Winsock Test app on Windows.
+     */
+    if (LOBYTE(wVersionRequested) == 1)
+    {
+        lpWSAData->iMaxSockets = 32767;
+        lpWSAData->iMaxUdpDg = 65467;
+    } 
+    else
+    {
+        lpWSAData->iMaxSockets = 0;
+        lpWSAData->iMaxUdpDg = 0;
+    }
+
+    /* Enter the startup syncronization lock */
+    WsStartupLock();
+
+    /* Now setup all our objects */
+    while (TRUE)
+    {
+        /* Make sure we don't already have a process */
+        CurrentProcess = WsGetProcess();
+        if (CurrentProcess) break;
+
+        /* Setup the process object support */
+        ErrorCode = WsProcStartup();
+        if (ErrorCode != ERROR_SUCCESS) break;
+
+        /* Setup the process object support */
+        ErrorCode = WsSockStartup();
+        if (ErrorCode != ERROR_SUCCESS) break;
+
+        /* Setup the process object support */
+        ErrorCode = WsThreadStartup();
+        if (ErrorCode != ERROR_SUCCESS) break;
+
+        /* Try getting the process now */
+        CurrentProcess = WsGetProcess();
+        if (!CurrentProcess)
+        {
+            /* Something is weird... */
+            ErrorCode = WSASYSNOTREADY;
+            break;
+        }
+    }
+
+    /* Check if all worked */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Set the requested version */
+        WsProcSetVersion(CurrentProcess, wVersionRequested);
+
+        /* Increase the reference count */
+        InterlockedIncrement(&CurrentProcess->RefCount);
+    }
+
+    /* Leave the startup lock */
+    WsStartupUnlock();
+
+    /* Return any Error */
+    return ErrorCode;
+}
diff --git a/reactos/dll/win32/ws2_32_new/src/wsautil.c b/reactos/dll/win32/ws2_32_new/src/wsautil.c
new file mode 100644 (file)
index 0000000..9881d97
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS WinSock 2 API
+ * FILE:        wsautil.c
+ * PURPOSE:     Winsock Utility Functions
+ * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "ws2_32.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+HKEY
+WSAAPI
+WsOpenRegistryRoot(VOID)
+{
+    HKEY WinsockRootKey;
+    INT ErrorCode;
+    ULONG CreateDisposition;
+
+    /* Open Registry Key */
+    ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                             WINSOCK_ROOT,
+                             0,
+                             MAXIMUM_ALLOWED,
+                             &WinsockRootKey);
+    
+    /* Check if it wasn't found */
+    if (ErrorCode == ERROR_FILE_NOT_FOUND)
+    {
+        /* Create it */
+        RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                       WINSOCK_ROOT,
+                       0,
+                       NULL,
+                       REG_OPTION_NON_VOLATILE,
+                       KEY_ALL_ACCESS,
+                       NULL,
+                       &WinsockRootKey,
+                       &CreateDisposition);
+    }
+    else if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* It already exists */
+        CreateDisposition = REG_OPENED_EXISTING_KEY;
+    }
+
+    /* Check for failure */
+    if (ErrorCode != ERROR_SUCCESS) return NULL;
+
+    /* Check if we had to create a new key */
+    if (CreateDisposition == REG_CREATED_NEW_KEY)
+    {
+        /* Write the Winsock Version */
+        RegSetValueEx(WinsockRootKey,
+                      "WinSock_Registry_Version",
+                      0,
+                      REG_SZ,
+                      (BYTE*)"2.2",
+                      4);
+    }
+    else
+    {
+        /* Read the Winsock Version */
+    }
+
+    /* Return the key */
+    return WinsockRootKey;
+}
+
+BOOL
+WSAAPI
+WsCheckCatalogState(IN HANDLE Event)
+{
+    DWORD Return;
+
+    /* Wait for the object */
+    Return = WaitForSingleObject(Event, 0);
+
+    /* Check for the value */
+    if (Return == WAIT_OBJECT_0) return TRUE;
+
+    /* If it timedout or anything else, return false */
+    return FALSE;
+}
+
+INT
+WSAAPI
+WsApiProlog(OUT PWSPROCESS *Process,
+            OUT PWSTHREAD *Thread)
+{
+    INT ErrorCode = WSANOTINITIALISED;
+
+    /* Try to get the current process */
+    if ((*Process = WsGetProcess()))
+    {
+        /* And the current thread */
+        ErrorCode = WsThreadGetCurrentThread(*Process, Thread);
+    }
+
+    /* Return init status */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WsSlowProlog(VOID)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+
+    /* Call the prolog */
+    return WsApiProlog(&Process, &Thread);
+}
+
+INT
+WSAAPI
+WsSlowPrologTid(OUT LPWSATHREADID *ThreadId)
+{
+    PWSPROCESS Process;
+    PWSTHREAD Thread;
+    INT ErrorCode;
+
+    /* Call the prolog */
+    ErrorCode = WsApiProlog(&Process, &Thread);
+
+    /* Check for success */
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        /* Return the Thread ID */
+        *ThreadId = &Thread->WahThreadId;
+    }
+
+    /* Return status */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+WsSetupCatalogProtection(IN HKEY CatalogKey,
+                         IN HANDLE CatalogEvent,
+                         OUT LPDWORD UniqueId)
+{
+    INT ErrorCode;
+    HKEY RegistryKey;
+    DWORD NewUniqueId;
+    CHAR KeyBuffer[32];
+    DWORD RegType = REG_DWORD;
+    DWORD RegSize = sizeof(DWORD);
+
+    /* Start loop */
+    do
+    {
+        /* Ask for notifications */
+        ErrorCode = RegNotifyChangeKeyValue(CatalogKey,
+                                            FALSE,
+                                            REG_NOTIFY_CHANGE_NAME,
+                                            CatalogEvent,
+                                            TRUE);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Normalize error code */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Read the current ID */
+        ErrorCode = RegQueryValueEx(CatalogKey,
+                                    "Serial_Access_Num",
+                                    0,
+                                    &RegType,
+                                    (LPBYTE)&NewUniqueId,
+                                    &RegSize);
+        if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Critical failure */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* Try to open it for writing */
+        sprintf(KeyBuffer, "%08.8lX", NewUniqueId);
+        ErrorCode = RegOpenKeyEx(CatalogKey,
+                                 KeyBuffer,
+                                 0,
+                                 MAXIMUM_ALLOWED,
+                                 &RegistryKey);
+
+        /* If the key doesn't exist or is being delete, that's ok for us */
+        if ((ErrorCode == ERROR_FILE_NOT_FOUND) ||
+            (ErrorCode == ERROR_KEY_DELETED))
+        {
+            /* Set success and return the new ID */
+            ErrorCode = ERROR_SUCCESS;
+            *UniqueId = NewUniqueId;
+            break;
+        }
+        else if (ErrorCode != ERROR_SUCCESS)
+        {
+            /* Any other failure is bad */
+            ErrorCode = WSASYSCALLFAILURE;
+            break;
+        }
+
+        /* If we could actually open the key, someone is using it :/ */
+        ErrorCode = RegCloseKey(RegistryKey);
+
+        /* In case we break out prematurely */
+        ErrorCode = WSANO_RECOVERY;
+
+        /* Keep looping until they let go of the registry writing */
+    } while (!WaitForSingleObject(CatalogEvent, 180 * 1000));
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+INT
+WSAAPI
+MapUnicodeProtocolInfoToAnsi(IN LPWSAPROTOCOL_INFOW UnicodeInfo,
+                             OUT LPWSAPROTOCOL_INFOA AnsiInfo)
+{
+    INT ReturnValue;
+
+    /* Copy all the data that doesn't need converting */
+    RtlCopyMemory(AnsiInfo,
+                  UnicodeInfo,
+                  FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol));
+
+    /* Now convert the protocol string */
+    ReturnValue = WideCharToMultiByte(CP_ACP,
+                                      0,
+                                      UnicodeInfo->szProtocol,
+                                      -1,
+                                      AnsiInfo->szProtocol,
+                                      sizeof(AnsiInfo->szProtocol),
+                                      NULL,
+                                      NULL);
+    if (!ReturnValue) return WSASYSCALLFAILURE;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+VOID
+WSAAPI
+WEP(VOID)
+{
+    return;
+}
diff --git a/reactos/dll/win32/ws2_32_new/ws2_32.def b/reactos/dll/win32/ws2_32_new/ws2_32.def
new file mode 100644 (file)
index 0000000..b04ec26
--- /dev/null
@@ -0,0 +1,124 @@
+; WS2_32.DLL - Windows Sockets 2 DLL
+
+LIBRARY ws2_32.dll
+
+EXPORTS
+WEP@0 @500
+WPUCompleteOverlappedRequest@20 @28
+WSAAccept@20 @29
+WSAAddressToStringA@20 @30
+WSAAddressToStringW@20 @31
+WSAAsyncGetHostByAddr@28 @102
+WSAAsyncGetHostByNam@20e @103
+WSAAsyncGetProtoByName@20 @105
+WSAAsyncGetProtoByNumber@20 @104
+WSAAsyncGetServByName@24 @107
+WSAAsyncGetServByPort@24 @106
+WSAAsyncSelect@16 @101
+WSACancelAsyncRequest@4 @108
+WSACancelBlockingCall@0 @113
+WSACleanup@0 @116
+WSACloseEvent@4 @32
+WSAConnect@28 @33
+WSACreateEvent@0 @34
+WSADuplicateSocketA@12 @35
+WSADuplicateSocketW@12 @36
+WSAEnumNameSpaceProvidersA@8 @37
+WSAEnumNameSpaceProvidersW@8 @38
+WSAEnumNetworkEvents@12 @39
+WSAEnumProtocolsA@12 @40
+WSAEnumProtocolsW@12 @41
+WSAEventSelect @42
+WSAGetLastError @111
+WSAGetOverlappedResult @43
+WSAGetQOSByName @44
+WSAGetServiceClassInfoA @45
+WSAGetServiceClassInfoW @46
+WSAGetServiceClassNameByClassIdA @47
+WSAGetServiceClassNameByClassIdW @48
+WSAHtonl @49
+WSAHtons @50
+WSAInstallServiceClassA @58
+WSAInstallServiceClassW @59
+WSAIoctl @60
+WSAIsBlocking @114
+WSAJoinLeaf @61
+WSALookupServiceBeginA @62
+WSALookupServiceBeginW @63
+WSALookupServiceEnd @64
+WSALookupServiceNextA @65
+WSALookupServiceNextW @66
+WSANSPIoctl @67
+WSANtohl @68
+WSANtohs @69
+WSAProviderConfigChange @70
+WSARecv @71
+WSARecvDisconnect @72
+WSARecvFrom @73
+WSARemoveServiceClass @74
+WSAResetEvent @75
+WSASend @76
+WSASendDisconnect @77
+WSASendTo @78
+WSASetBlockingHook @109
+WSASetEvent @79
+WSASetLastError @112
+WSASetServiceA @80
+WSASetServiceW @81
+WSASocketA @82
+WSASocketW @83
+WSAStartup @115
+WSAStringToAddressA @84
+WSAStringToAddressW @85
+WSAUnhookBlockingHook @110
+WSAWaitForMultipleEvents @86
+WSApSetPostRoutine @26
+FreeAddrInfoW=freeaddrinfo @27
+WSCDeinstallProvider @87
+WSCEnableNSProvider @88
+WSCEnumProtocols @89
+WSCGetProviderPath @90
+WSCInstallNameSpace @91
+WSCInstallProvider @92
+WSCUnInstallNameSpace @93
+WSCUpdateProvider @94
+WSCWriteNameSpaceOrder @95
+WSCWriteProviderOrder @96
+__WSAFDIsSet @151
+accept @1
+bind @2
+closesocket @3
+connect @4
+freeaddrinfo @97
+getaddrinfo @98
+gethostbyaddr @51
+gethostbyname @52
+gethostname @57
+getnameinfo @99
+getpeername @5
+getprotobyname @53
+getprotobynumber @54
+getservbyname @55
+getservbyport @56
+getsockname @6
+getsockopt @7
+htonl @8
+htons @9
+inet_addr @11
+inet_ntoa @12
+ioctlsocket @10
+listen @13
+ntohl @14
+ntohs @15
+recv @16
+recvfrom @17
+select @18
+send @19
+sendto @20
+setsockopt @21
+shutdown @22
+socket @23
+GetAddrInfoW @24
+GetNameInfoW @25
+
+; EOF
diff --git a/reactos/dll/win32/ws2_32_new/ws2_32.rbuild b/reactos/dll/win32/ws2_32_new/ws2_32.rbuild
new file mode 100644 (file)
index 0000000..2371317
--- /dev/null
@@ -0,0 +1,52 @@
+<module name="ws2_32_new" type="win32dll" baseaddress="${BASEADDRESS_WS2_32}" installbase="system32" installname="ws2_32.dll" unicode="yes">
+       <importlibrary definition="ws2_32.spec" />
+       <include base="ws2_32">include</include>
+       <include base="ReactOS">include/reactos/wine</include>
+       <define name="LE" />
+       <library>wine</library>
+       <library>ntdll</library>
+       <library>kernel32</library>
+       <library>user32</library>
+       <library>advapi32</library>
+       <library>dnsapi</library>
+       <directory name="src">
+               <file>addrconv.c</file>
+               <file>addrinfo.c</file>
+               <file>async.c</file>
+               <file>bhook.c</file>
+               <file>dcatalog.c</file>
+               <file>dcatitem.c</file>
+               <file>dllmain.c</file>
+               <file>dprocess.c</file>
+               <file>dprovide.c</file>
+               <file>dsocket.c</file>
+               <file>dthread.c</file>
+               <file>dupsock.c</file>
+               <file>enumprot.c</file>
+               <file>event.c</file>
+    <file>getproto.c</file>
+    <file>getxbyxx.c</file>
+    <file>ioctl.c</file>
+    <file>nscatalo.c</file>
+    <file>nscatent.c</file>
+    <file>nspinstl.c</file>
+    <file>nsprovid.c</file>
+    <file>nsquery.c</file>
+    <file>qos.c</file>
+    <file>qshelpr.c</file>
+    <file>rasdial.c</file>
+    <file>recv.c</file>
+    <file>rnr.c</file>
+    <file>scihlpr.c</file>
+    <file>select.c</file>
+    <file>send.c</file>
+    <file>sockctrl.c</file>
+    <file>socklife.c</file>
+    <file>spinstal.c</file>
+    <file>sputil.c</file>
+    <file>startup.c</file>
+    <file>wsautil.c</file>
+       </directory>
+       <file>ws2_32.rc</file>
+</module>
+
diff --git a/reactos/dll/win32/ws2_32_new/ws2_32.rc b/reactos/dll/win32/ws2_32_new/ws2_32.rc
new file mode 100644 (file)
index 0000000..20f8c9b
--- /dev/null
@@ -0,0 +1,7 @@
+/* $Id: ws2_32.rc 23580 2006-08-14 17:26:36Z gedmurphy $ */
+
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Windows Sockets 2 DLL\0"
+#define REACTOS_STR_INTERNAL_NAME      "ws2_32\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "ws2_32.dll\0"
+#include <reactos/version.rc>