[MSWSOCK] Rearrange the function places to avoid forward declarations and code formatting
authorPeter Hater <7element@mail.bg>
Fri, 2 Jun 2017 21:57:37 +0000 (21:57 +0000)
committerPeter Hater <7element@mail.bg>
Fri, 2 Jun 2017 21:57:37 +0000 (21:57 +0000)
svn path=/trunk/; revision=74755

reactos/dll/win32/mswsock/nsplookup.c

index 24d4174..e86f4d4 100644 (file)
@@ -23,34 +23,32 @@ WINE_DEFAULT_DEBUG_CHANNEL(mswsock);
 #define NSP_CALLID_SERVICEBYNAME 0x0004
 
 #ifndef BUFSIZ
-#define BUFSIZ 1024
+  #define BUFSIZ 1024
 #endif // BUFSIZ
 #ifndef WS2_INTERNAL_MAX_ALIAS
-#define WS2_INTERNAL_MAX_ALIAS 512
+  #define WS2_INTERNAL_MAX_ALIAS 512
 #endif // WS2_INTERNAL_MAX_ALIAS
 
-//#define IP_LOCALHOST 0x0100007F
-
 //#define NSP_REDIRECT
 
 typedef struct {
-  WCHAR* hostnameW;
-  DWORD addr4;
-  WCHAR* servnameW;
-  WCHAR* servprotoW;
-  CHAR** servaliasesA; /* array */
-  WORD servport;
+    WCHAR* hostnameW;
+    DWORD addr4;
+    WCHAR* servnameW;
+    WCHAR* servprotoW;
+    CHAR** servaliasesA; /* array */
+    WORD servport;
 } WSHOSTINFOINTERN, *PWSHOSTINFOINTERN;
 
 typedef struct {
-  GUID providerId; /* Provider-ID */
-  DWORD dwControlFlags; /* dwControlFlags (WSALookupServiceBegin) */
-  DWORD CallID; /* List for LookupServiceNext-Calls */
-  DWORD CallIDCounter; /* call-count of the current CallID. */
-  WCHAR* hostnameW; /* hostbyname */
+    GUID providerId; /* Provider-ID */
+    DWORD dwControlFlags; /* dwControlFlags (WSALookupServiceBegin) */
+    DWORD CallID; /* List for LookupServiceNext-Calls */
+    DWORD CallIDCounter; /* call-count of the current CallID. */
+    WCHAR* hostnameW; /* hostbyname */
 #ifdef NSP_REDIRECT
-  HANDLE rdrLookup;
-  NSP_ROUTINE rdrproc;
+    HANDLE rdrLookup;
+    NSP_ROUTINE rdrproc;
 #endif
 } WSHANDLEINTERN, *PWSHANDLEINTERN;
 
@@ -89,911 +87,589 @@ NSP_ROUTINE rdrproc_nla;
 
 #endif /* NSP_REDIRECT */
 
-/* Forwards */
-INT
-WINAPI
-mswNSPStartup(
-  LPGUID lpProviderId,
-  LPNSP_ROUTINE lpRout);
+/* Implementations - Internal */
 
-INT
-NSP_LookupServiceBeginW(
-  PWSHANDLEINTERN data,
-  CHAR* hostnameA,
-  WCHAR* hostnameW,
-  DWORD CallID);
+/*
+    hostnameA / hostnameW
+    * only used by HOSTBYNAME
+    * only one should be set
 
+*/
 INT
-NSP_LookupServiceNextW(
-  _In_ PWSHANDLEINTERN data,
-  _In_ DWORD dwControlFlags,
-  _Inout_ LPWSAQUERYSETW lpRes,
-  _Inout_ LPDWORD lpResLen);
+NSP_LookupServiceBeginW(PWSHANDLEINTERN data,
+                        CHAR* hostnameA,
+                        WCHAR* hostnameW,
+                        DWORD CallID)
+{
+    HANDLE hHeap;
 
-INT
-NSP_GetHostNameHeapAllocW(
-  _Out_ WCHAR** hostname);
+    TRACE("NSP_LookupServiceBeginW %p %p %p %lx\n", data, hostnameA, hostnameW, CallID);
+    if (data->CallID != 0)
+        return WSAEFAULT;
 
-INT
-NSP_GetHostByNameHeapAllocW(
-  _In_ PWSHANDLEINTERN data,
-  _In_ DWORD dwControlFlags,
-  _Out_ PWSHOSTINFOINTERN hostinfo);
+    data->CallID = CallID;
 
-INT
-NSP_GetServiceByNameHeapAllocW(
-  _In_ PWSHANDLEINTERN data,
-  _In_ DWORD dwControlFlags,
-  _Out_ PWSHOSTINFOINTERN hostinfo);
+    if ((CallID == NSP_CALLID_HOSTBYNAME) ||
+        (CallID == NSP_CALLID_SERVICEBYNAME))
+    {
+        hHeap = GetProcessHeap();
 
-/* Implementations - Internal */
+        if (data->hostnameW != NULL)
+            HeapFree(hHeap, 0, data->hostnameW);
 
-INT
-WSAAPI
-mwsNSPCleanUp(_In_ LPGUID lpProviderId)
-{
-    //WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    //return ERROR_CALL_NOT_IMPLEMENTED;
-    return ERROR_SUCCESS;
-}
+        if (hostnameA != NULL)
+        {
+            data->hostnameW = StrA2WHeapAlloc(hHeap, hostnameA);
+        }
+        else
+        {
+            data->hostnameW = StrCpyHeapAllocW(hHeap, hostnameW);
+        }
+    }
+    else
+    {
+        ERR("NSP_LookupServiceBeginW unsupported CallID\n");
+        WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return ERROR_CALL_NOT_IMPLEMENTED;
+    }
 
-INT
-mwsNSPInit(VOID)
-{
     return ERROR_SUCCESS;
 }
 
 INT
-WSAAPI
-mwsNSPLookupServiceBegin(_In_ LPGUID lpProviderId,
-                         _In_ LPWSAQUERYSETW lpqsRestrictions,
-                         _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
-                         _In_ DWORD dwControlFlags,
-                         _Out_ LPHANDLE lphLookup)
+NSP_GetHostNameHeapAllocW(_Out_ WCHAR** hostname)
 {
-    PWSHANDLEINTERN pLook;
-    int wsaErr;
+    WCHAR* name;
+    HANDLE hHeap = GetProcessHeap();
+    DWORD bufCharLen = 0;
 
-    TRACE("mwsNSPLookupServiceBegin %p %p %p %lx %p\n", lpProviderId, lpqsRestrictions, lpServiceClassInfo, dwControlFlags, lphLookup);
-    if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
-    {
-        //OK
-        TRACE("TCPIP query\n");
-    }
-    else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
+    TRACE("NSP_GetHostNameHeapAllocW %p\n", hostname);
+    /* FIXME Use DnsGetHostName_W when available */
+    GetComputerNameExW(ComputerNameDnsHostname, NULL, &bufCharLen);
+    if (!bufCharLen)
     {
-        ERR("NLA queries are not supported yet\n");
-        WSASetLastError(WSASERVICE_NOT_FOUND);
+        ERR("NSP_GetHostNameHeapAllocW zero size for computername returned\n");
+        WSASetLastError(WSAEFAULT);
         return SOCKET_ERROR;
     }
-    else
-    {
-        ERR("Unsupported GUID\n");
-        return ERROR_CALL_NOT_IMPLEMENTED;
-    }
-
-    /* allocate internal structure */
-    pLook = HeapAlloc(GetProcessHeap(), 0, sizeof(WSHANDLEINTERN));
-    if (!pLook)
+    name = HeapAlloc(hHeap, 0, bufCharLen*sizeof(WCHAR));
+    if (!GetComputerNameExW(ComputerNameDnsHostname,
+                            name,
+                            &bufCharLen))
     {
-        ERR("Error allocating %d for handle\n", sizeof(WSHANDLEINTERN));
+        ERR("NSP_GetHostNameHeapAllocW error obtaining computername %lx\n", GetLastError());
+        HeapFree(hHeap, 0, name);
         WSASetLastError(WSAEFAULT);
         return SOCKET_ERROR;
     }
 
-    *lphLookup = (HANDLE)pLook;
-
-    RtlZeroMemory(pLook, sizeof(*pLook));
+    *hostname = name;
+    return ERROR_SUCCESS;
+}
 
-    /* Anyway the ControlFlags "should" be needed
-       in NSPLookupServiceNext. (see doku) But
-       thats not the fact ATM. */
-    pLook->dwControlFlags = dwControlFlags;
-    pLook->providerId = *lpProviderId;
+INT
+NSP_GetHostByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
+                            _In_ DWORD dwControlFlags,
+                            _Out_ PWSHOSTINFOINTERN hostinfo)
+{
+    HANDLE hHeap = GetProcessHeap();
+    DNS_STATUS dns_status = { 0 };
+    /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
+    PDNS_RECORDW dp;
+    PDNS_RECORDW curr;
+    INT result = ERROR_SUCCESS;
+    DWORD dwQueryFlags = DNS_QUERY_STANDARD;
+    PWCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
+    int AliasIndex = 0;
 
-#ifdef NSP_REDIRECT
+    TRACE("NSP_GetHostByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
+    /* needed to be cleaned up if != NULL */
+    dp = NULL;
 
-    if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
-    {
-        pLook->rdrproc = rdrproc_tcpip;
-    }
-    else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
-    {
-        pLook->rdrproc = rdrproc_nla;
-    }
-    else
+    if (!data->hostnameW)
     {
-        return ERROR_CALL_NOT_IMPLEMENTED;
+        result = ERROR_INVALID_PARAMETER;
+        goto cleanup;
     }
 
-    if (pLook->rdrproc.NSPLookupServiceBegin(lpProviderId,
-                                             lpqsRestrictions,
-                                             lpServiceClassInfo,
-                                             dwControlFlags,
-                                             &pLook->rdrLookup) == NO_ERROR)
-    {
-        wsaErr = NO_ERROR;
-    }
-    else
+    if ((data->dwControlFlags & LUP_DEEP) == 0)
     {
-        wsaErr = WSAGetLastError();
+        TRACE("NSP_GetHostByNameHeapAllocW LUP_DEEP is not specified. Disabling recursion\n");
+        dwQueryFlags |= DNS_QUERY_NO_RECURSION;
     }
 
-    /*
-    if (res)
-        res = WSAGetLastError();
-    */
-
-#else /* NSP_REDIRECT */
-
-    wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
-    if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_NULL))
+    /* DNS_TYPE_A: include/WinDNS.h */
+    /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
+    dns_status = DnsQuery_W(data->hostnameW,
+                            DNS_TYPE_A,
+                            dwQueryFlags,
+                            NULL /* extra dns servers */,
+                            &dp,
+                            NULL);
+    if (dns_status == ERROR_INVALID_NAME)
     {
-        ERR("NULL GUID service class is not implemented yet\n");
-        wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
+        ERR("NSP_GetHostByNameHeapAllocW invalid name\n");
+        WSASetLastError(WSAEFAULT);
+        result = ERROR_INVALID_PARAMETER;
+        goto cleanup;
     }
-    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_HOSTNAME))
+
+    if ((dns_status != 0) || (dp == NULL))
     {
-        TRACE("HOSTNAME GUID\n");
-        wsaErr = NSP_LookupServiceBeginW(pLook,
-                                         NULL,
-                                         NULL,
-                                         NSP_CALLID_HOSTNAME);
+        ERR("NSP_GetHostByNameHeapAllocW not found %lx %p\n", dns_status, dp);
+        result = WSAHOST_NOT_FOUND;
+        goto cleanup;
     }
-    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
-                         &guid_INET_HOSTADDRBYNAME))
+
+    //ASSERT(dp->wType == DNS_TYPE_A);
+    //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
+    curr = dp;
+    while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
     {
-        TRACE("INET_HOSTADDRBYNAME GUID\n");
-        wsaErr = NSP_LookupServiceBeginW(pLook,
-                                         NULL,
-                                         lpqsRestrictions->lpszServiceInstanceName,
-                                         NSP_CALLID_HOSTBYNAME);
+        if (curr->wType == DNS_TYPE_CNAME)
+        {
+            TRACE("NSP_GetHostByNameHeapAllocW found alias %ws\n", curr->Data.Cname.pNameHost);
+            Aliases[AliasIndex++] = curr->Data.Cname.pNameHost;
+        }
+        curr = curr->pNext;
     }
-    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
-                         &guid_INET_SERVICEBYNAME))
+
+    if (curr->wType != DNS_TYPE_A)
     {
-        TRACE("INET_SERVICEBYNAME\n");
-        wsaErr = NSP_LookupServiceBeginW(pLook,
-                                         NULL,
-                                         lpqsRestrictions->lpszServiceInstanceName,
-                                         NSP_CALLID_SERVICEBYNAME);
+        ERR("NSP_GetHostByNameHeapAllocW last record is not of type A %d\n", curr->wType);
+        result = WSASERVICE_NOT_FOUND;
+        goto cleanup;
     }
-    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
-                         &guid_INET_HOSTADDRBYINETSTRING))
+    hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, curr->pName);
+    hostinfo->addr4 = curr->Data.A.IpAddress;
+    if (AliasIndex)
     {
-        ERR("INET_HOSTADDRBYINETSTRING GUID service class is not implemented yet\n");
-        wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
+        hostinfo->servaliasesA = StrAryCpyHeapAllocWToA(hHeap, (WCHAR**)&Aliases);
     }
+    result = ERROR_SUCCESS;
 
-#endif /* NSP_REDIRECT */
+cleanup:
+    if (dp != NULL)
+        DnsRecordListFree(dp, DnsFreeRecordList);
 
-    if (wsaErr != NO_ERROR)
-    {
-        ERR("mwsNSPLookupServiceBegin wsaErr = %d\n", wsaErr);
-        WSASetLastError(wsaErr);
-        return SOCKET_ERROR;
-    }
-    return NO_ERROR;
+    return result;
 }
 
-INT
-WSAAPI
-mwsNSPLookupServiceNext(_In_ HANDLE hLookup,
-                        _In_ DWORD dwControlFlags,
-                        _Inout_ LPDWORD lpdwBufferLength,
-                        //_Out_writes_bytes_to_(*lpdwBufferLength, *lpdwBufferLength)
-                        LPWSAQUERYSETW lpqsResults)
-{
-    PWSHANDLEINTERN pLook = hLookup;
-    int wsaErr = 0;
-
-    TRACE("mwsNSPLookupServiceNext %p %lx %p %p\n", pLook, dwControlFlags, lpdwBufferLength, lpqsResults);
-#ifdef NSP_REDIRECT
+#define SKIPWS(ptr, act) \
+{while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
 
-    INT res = pLook->rdrproc.NSPLookupServiceNext(pLook->rdrLookup,
-                                                  dwControlFlags,
-                                                  lpdwBufferLength,
-                                                  lpqsResults);
-    wsaErr = WSAGetLastError();
-    if (res != ERROR_SUCCESS)
-    {
-        wsaErr = WSAGetLastError();
-
-        if (wsaErr == 0)
-            wsaErr = 0xFFFFFFFF;
-    }
-
-#else /* NSP_REDIRECT */
-
-    if ((lpdwBufferLength == NULL) || (*lpdwBufferLength == 0))
-    {
-        wsaErr = WSA_NOT_ENOUGH_MEMORY;
-        goto End;
-    }
-
-    RtlZeroMemory(lpqsResults, *lpdwBufferLength);
-    lpqsResults->dwSize = sizeof(*lpqsResults);
+#define SKIPANDMARKSTR(ptr, act) \
+{while(*ptr && !isspace(*ptr)) ptr++; \
+ if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
 
-    wsaErr = NSP_LookupServiceNextW(pLook,
-                                    dwControlFlags,
-                                    lpqsResults,
-                                    lpdwBufferLength);
+static
+BOOL
+DecodeServEntFromString(IN PCHAR ServiceString,
+                        OUT PCHAR *ServiceName,
+                        OUT PCHAR *PortNumberStr,
+                        OUT PCHAR *ProtocolStr,
+                        IN PCHAR *Aliases,
+                        IN DWORD MaxAlias)
+{
+    UINT NAliases = 0;
 
+    //WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
 
-#endif /* NSP_REDIRECT */
+    SKIPWS(ServiceString, return FALSE);
+    *ServiceName = ServiceString;
+    SKIPANDMARKSTR(ServiceString, return FALSE);
+    SKIPWS(ServiceString, return FALSE);
+    *PortNumberStr = ServiceString;
+    SKIPANDMARKSTR(ServiceString, ;);
 
-End:
-    if (wsaErr != 0)
+    while (*ServiceString && NAliases < MaxAlias - 1)
     {
-        ERR("mwsNSPLookupServiceNext wsaErr = %d\n", wsaErr);
-        WSASetLastError(wsaErr);
-        return SOCKET_ERROR;
+        SKIPWS(ServiceString, break);
+        if (*ServiceString)
+        {
+            SKIPWS(ServiceString, ;);
+            if (strlen(ServiceString))
+            {
+                //WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
+                *Aliases++ = ServiceString;
+                NAliases++;
+            }
+            SKIPANDMARKSTR(ServiceString, ;);
+        }
     }
-    return NO_ERROR;
-}
-
-INT
-WSAAPI
-mwsNSPIoCtl(_In_ HANDLE hLookup,
-            _In_ DWORD dwControlCode,
-            _In_reads_bytes_(cbInBuffer) LPVOID lpvInBuffer,
-            _In_ DWORD cbInBuffer,
-            _Out_writes_bytes_to_(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer,
-            _In_ DWORD cbOutBuffer,
-            _Out_ LPDWORD lpcbBytesReturned,
-            _In_opt_ LPWSACOMPLETION lpCompletion,
-            _In_ LPWSATHREADID lpThreadId)
-{
-    ERR("mwsNSPIoCtl not implemented %p %lx %p %ld %p %ld %p %p %p\n", hLookup, dwControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpCompletion, lpThreadId);
-    WSASetLastError(WSAEOPNOTSUPP);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
-INT
-WSAAPI
-mwsNSPLookupServiceEnd(_In_ HANDLE hLookup)
-{
-    PWSHANDLEINTERN pLook = (PWSHANDLEINTERN)hLookup;
-    HANDLE hHeap = GetProcessHeap();
-    INT res = NO_ERROR;
-
-    TRACE("mwsNSPLookupServiceEnd %p\n", pLook);
-#ifdef NSP_REDIRECT
-    res = pLook->rdrproc.NSPLookupServiceEnd(pLook->rdrLookup);
-#endif
+    *Aliases = NULL;
 
-    if (pLook->hostnameW != NULL)
-        HeapFree(hHeap, 0, pLook->hostnameW);
+    *ProtocolStr = strchr(*PortNumberStr, '/');
 
-    HeapFree(hHeap, 0, pLook);
-    return res;
-}
+    if (!*ProtocolStr)
+        return FALSE;
 
-INT
-WSAAPI
-mwsNSPSetService(_In_ LPGUID lpProviderId,
-                 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
-                 _In_ LPWSAQUERYSETW lpqsRegInfo,
-                 _In_ WSAESETSERVICEOP essOperation,
-                 _In_ DWORD dwControlFlags)
-{
-    ERR("mwsNSPSetService not implemented %p %p %p %d %lx %ld %p %p %p\n", lpProviderId, lpServiceClassInfo, lpqsRegInfo, essOperation, dwControlFlags);
-    WSASetLastError(WSAEOPNOTSUPP);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
+    **ProtocolStr = 0;
+    (*ProtocolStr)++;
 
-INT
-WSAAPI
-mwsNSPInstallServiceClass(_In_ LPGUID lpProviderId,
-                          _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
-{
-    ERR("mwsNSPInstallServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassInfo);
-    WSASetLastError(WSAEOPNOTSUPP);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
+    //WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
+    //           *ServiceName, *ProtocolStr, *PortNumberStr,
+    //            NAliases));
 
-INT
-WSAAPI
-mwsNSPRemoveServiceClass(_In_ LPGUID lpProviderId,
-                         _In_ LPGUID lpServiceClassId)
-{
-    ERR("mwsNSPRemoveServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassId);
-    WSASetLastError(WSAEOPNOTSUPP);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    return TRUE;
 }
 
-INT
+HANDLE
 WSAAPI
-mwsNSPGetServiceClassInfo(_In_ LPGUID lpProviderId,
-                          _In_ LPDWORD lpdwBufSize,
-                          _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
-{
-    ERR("mwsNSPGetServiceClassInfo not implemented %p %p %p\n", lpProviderId, lpdwBufSize, lpServiceClassInfo);
-    WSASetLastError(WSAEOPNOTSUPP);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
-/*
-    hostnameA / hostnameW
-    * only used by HOSTBYNAME
-    * only one should be set
-
-*/
-INT
-NSP_LookupServiceBeginW(PWSHANDLEINTERN data,
-                        CHAR* hostnameA,
-                        WCHAR* hostnameW,
-                        DWORD CallID)
+OpenNetworkDatabase(_In_ LPCWSTR Name)
 {
-    HANDLE hHeap;
-
-    TRACE("NSP_LookupServiceBeginW %p %p %p %lx\n", data, hostnameA, hostnameW, CallID);
-    if (data->CallID != 0)
-        return WSAEFAULT;
+    PWSTR ExpandedPath;
+    PWSTR DatabasePath;
+    INT ErrorCode;
+    HKEY DatabaseKey;
+    DWORD RegType;
+    DWORD RegSize = 0;
+    size_t StringLength;
+    HANDLE Handle;
 
-    data->CallID = CallID;
+    TRACE("OpenNetworkDatabase %p\n", Name);
+    ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
+    if (!ExpandedPath)
+        return INVALID_HANDLE_VALUE;
 
-    if ((CallID == NSP_CALLID_HOSTBYNAME) ||
-        (CallID == NSP_CALLID_SERVICEBYNAME))
+    /* Open the database path key */
+    ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                             L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+                             0,
+                             KEY_READ,
+                             &DatabaseKey);
+    if (ErrorCode == NO_ERROR)
     {
-        hHeap = GetProcessHeap();
-
-        if (data->hostnameW != NULL)
-            HeapFree(hHeap, 0, data->hostnameW);
+        TRACE("OpenNetworkDatabase registry key for network database exist\n");
+        /* Read the actual path */
+        ErrorCode = RegQueryValueEx(DatabaseKey,
+                                    L"DatabasePath",
+                                    NULL,
+                                    &RegType,
+                                    NULL,
+                                    &RegSize);
 
-        if (hostnameA != NULL)
+        if (!RegSize)
         {
-            data->hostnameW = StrA2WHeapAlloc(hHeap, hostnameA);
+            ERR("OpenNetworkDatabase RegQueryValueEx failed to return size for DatabasePath %lx\n", ErrorCode);
+            RegCloseKey(DatabaseKey);
+            HeapFree(GetProcessHeap(), 0, ExpandedPath);
+            return INVALID_HANDLE_VALUE;
         }
-        else
+        DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
+        if (!DatabasePath)
         {
-            data->hostnameW = StrCpyHeapAllocW(hHeap, hostnameW);
+            ERR("OpenNetworkDatabase could not allocate %d for DatabasePath\n", RegSize);
+            RegCloseKey(DatabaseKey);
+            HeapFree(GetProcessHeap(), 0, ExpandedPath);
+            return INVALID_HANDLE_VALUE;
+        }
+
+        /* Read the actual path */
+        ErrorCode = RegQueryValueEx(DatabaseKey,
+                                    L"DatabasePath",
+                                    NULL,
+                                    &RegType,
+                                    (LPBYTE)DatabasePath,
+                                    &RegSize);
+
+        /* Close the key */
+        RegCloseKey(DatabaseKey);
+
+        if (ErrorCode)
+        {
+            ERR("OpenNetworkDatabase RegQueryValueEx failed to return value for DatabasePath %lx\n", ErrorCode);
+            HeapFree(GetProcessHeap(), 0, DatabasePath);
+            HeapFree(GetProcessHeap(), 0, ExpandedPath);
+            return INVALID_HANDLE_VALUE;
         }
+
+        /* Expand the name */
+        ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
+
+        HeapFree(GetProcessHeap(), 0, DatabasePath);
     }
     else
     {
-        ERR("NSP_LookupServiceBeginW unsupported CallID\n");
-        WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-        return ERROR_CALL_NOT_IMPLEMENTED;
+        TRACE("OpenNetworkDatabase registry key for network database doesn't exist\n");
+        /* Use defalt path */
+        GetSystemDirectory(ExpandedPath, MAX_PATH);
+        StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
+        if (ExpandedPath[StringLength - 1] != L'\\')
+        {
+            /* It isn't, so add it ourselves */
+            StringCchCat(ExpandedPath, MAX_PATH, L"\\");
+        }
+        StringCchCat(ExpandedPath, MAX_PATH, L"DRIVERS\\ETC\\");
     }
 
-    return ERROR_SUCCESS;
-}
-
-INT
-NSP_GetHostNameHeapAllocW(_Out_ WCHAR** hostname)
-{
-    WCHAR* name;
-    HANDLE hHeap = GetProcessHeap();
-    DWORD bufCharLen = 0;
-
-    TRACE("NSP_GetHostNameHeapAllocW %p\n", hostname);
-    /* FIXME Use DnsGetHostName_W when available */
-    GetComputerNameExW(ComputerNameDnsHostname, NULL, &bufCharLen);
-    if (!bufCharLen)
-    {
-        ERR("NSP_GetHostNameHeapAllocW zero size for computername returned\n");
-        WSASetLastError(WSAEFAULT);
-        return SOCKET_ERROR;
-    }
-    name = HeapAlloc(hHeap, 0, bufCharLen*sizeof(WCHAR));
-    if (!GetComputerNameExW(ComputerNameDnsHostname,
-                            name,
-                            &bufCharLen))
+    /* Make sure that the path is backslash-terminated */
+    StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
+    if (ExpandedPath[StringLength - 1] != L'\\')
     {
-        ERR("NSP_GetHostNameHeapAllocW error obtaining computername %lx\n", GetLastError());
-        HeapFree(hHeap, 0, name);
-        WSASetLastError(WSAEFAULT);
-        return SOCKET_ERROR;
+        /* It isn't, so add it ourselves */
+        StringCchCat(ExpandedPath, MAX_PATH, L"\\");
     }
 
-    *hostname = name;
-    return ERROR_SUCCESS;
+    /* Add the database name */
+    StringCchCat(ExpandedPath, MAX_PATH, Name);
+
+    /* Return a handle to the file */
+    Handle = CreateFile(ExpandedPath,
+                        FILE_READ_DATA,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        FILE_ATTRIBUTE_NORMAL,
+                        NULL);
+
+    HeapFree(GetProcessHeap(), 0, ExpandedPath);
+    return Handle;
 }
 
 INT
-NSP_GetHostByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
-                            _In_ DWORD dwControlFlags,
-                            _Out_ PWSHOSTINFOINTERN hostinfo)
+NSP_GetServiceByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
+                               _In_ DWORD dwControlFlags,
+                               _Out_ PWSHOSTINFOINTERN hostinfo)
 {
-    HANDLE hHeap = GetProcessHeap();
-    DNS_STATUS dns_status = { 0 };
-    /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
-    PDNS_RECORDW dp;
-    PDNS_RECORDW curr;
-    INT result = ERROR_SUCCESS;
-    DWORD dwQueryFlags = DNS_QUERY_STANDARD;
-    PWCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
-    int AliasIndex = 0;
-
-    TRACE("NSP_GetHostByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
-    /* needed to be cleaned up if != NULL */
-    dp = NULL;
-
+    BOOL Found = FALSE;
+    HANDLE ServicesFile;
+    CHAR ServiceDBData[BUFSIZ * sizeof(WCHAR)] = { 0 };
+    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
+    ProtocolStr = 0, Comment = 0, EndValid;
+    PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
+    PCHAR* AliasPtr;
+    UINT i = 0;
+    DWORD ReadSize = 0;
+    HANDLE hHeap;
+    PCHAR nameA = NULL;
+    PCHAR nameServiceA = NULL;
+    PCHAR nameProtoA = NULL;
+    INT res = WSANO_RECOVERY;
+    
+    TRACE("NSP_GetServiceByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
     if (!data->hostnameW)
     {
-        result = ERROR_INVALID_PARAMETER;
-        goto cleanup;
+        ERR("NSP_GetServiceByNameHeapAllocW service name not provided\n");
+        res = WSANO_RECOVERY;
+        goto End;
     }
 
-    if ((data->dwControlFlags & LUP_DEEP) == 0)
-    {
-        TRACE("NSP_GetHostByNameHeapAllocW LUP_DEEP is not specified. Disabling recursion\n");
-        dwQueryFlags |= DNS_QUERY_NO_RECURSION;
-    }
+    hHeap = GetProcessHeap();
+    nameA = StrW2AHeapAlloc(hHeap, data->hostnameW);
 
-    /* DNS_TYPE_A: include/WinDNS.h */
-    /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
-    dns_status = DnsQuery_W(data->hostnameW,
-                            DNS_TYPE_A,
-                            dwQueryFlags,
-                            NULL /* extra dns servers */,
-                            &dp,
-                            NULL);
-    if (dns_status == ERROR_INVALID_NAME)
+    /* nameA has the form <service-name>/<protocol>
+       we split these now */
+    nameProtoA = strchr(nameA, '/');
+    if (nameProtoA == NULL)
     {
-        ERR("NSP_GetHostByNameHeapAllocW invalid name\n");
-        WSASetLastError(WSAEFAULT);
-        result = ERROR_INVALID_PARAMETER;
-        goto cleanup;
+        ERR("NSP_GetServiceByNameHeapAllocW invalid service name %s\n", nameA);
+        res = WSANO_RECOVERY;
+        goto End;
     }
 
-    if ((dns_status != 0) || (dp == NULL))
-    {
-        ERR("NSP_GetHostByNameHeapAllocW not found %lx %p\n", dns_status, dp);
-        result = WSAHOST_NOT_FOUND;
-        goto cleanup;
-    }
+    nameProtoA++;
+    i = (DWORD)(nameProtoA - nameA - 1);
+    nameServiceA = (PCHAR)HeapAlloc(hHeap, 0, i + 1);
+    StringCbCopyA(nameServiceA, i + 1, nameA);
+    nameServiceA[i] = '\0';
 
-    //ASSERT(dp->wType == DNS_TYPE_A);
-    //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
-    curr = dp;
-    while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
+    ServicesFile = OpenNetworkDatabase(L"services");
+    if (ServicesFile == INVALID_HANDLE_VALUE)
     {
-        if (curr->wType == DNS_TYPE_CNAME)
-        {
-            TRACE("NSP_GetHostByNameHeapAllocW found alias %ws\n", curr->Data.Cname.pNameHost);
-            Aliases[AliasIndex++] = curr->Data.Cname.pNameHost;
-        }
-        curr = curr->pNext;
+        ERR("NSP_GetServiceByNameHeapAllocW unable to open services file\n");
+        return WSANO_RECOVERY;
     }
 
-    if (curr->wType != DNS_TYPE_A)
+    /* Scan the services file ...
+    *
+    * We will be share the buffer on the lines. If the line does not fit in
+    * the buffer, then moving it to the beginning of the buffer and read
+    * the remnants of line from file.
+    */
+
+    /* Initial Read */
+    if (!ReadFile(ServicesFile,
+                  ServiceDBData,
+                  sizeof( ServiceDBData ) - 1,
+                  &ReadSize,
+                  NULL))
     {
-        ERR("NSP_GetHostByNameHeapAllocW last record is not of type A %d\n", curr->wType);
-        result = WSASERVICE_NOT_FOUND;
-        goto cleanup;
+        ERR("NSP_GetServiceByNameHeapAllocW can't read services file %lx\n", GetLastError());
+        CloseHandle(ServicesFile);
+        return WSANO_RECOVERY;
     }
-    hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, curr->pName);
-    hostinfo->addr4 = curr->Data.A.IpAddress;
-    if (AliasIndex)
+
+    ThisLine = NextLine = ServiceDBData;
+    EndValid = ServiceDBData + ReadSize;
+    ServiceDBData[sizeof(ServiceDBData) - 1] = '\0';
+
+    while (ReadSize)
     {
-        hostinfo->servaliasesA = StrAryCpyHeapAllocWToA(hHeap, (WCHAR**)&Aliases);
-    }
-    result = ERROR_SUCCESS;
+        for (; *NextLine != '\r' && *NextLine != '\n'; NextLine++)
+        {
+            if (NextLine == EndValid)
+            {
+                int LineLen = NextLine - ThisLine;
 
-cleanup:
-    if (dp != NULL)
-        DnsRecordListFree(dp, DnsFreeRecordList);
+                if (ThisLine == ServiceDBData)
+                {
+                    ERR("NSP_GetServiceByNameHeapAllocW line too long\n");
+                    CloseHandle(ServicesFile);
+                    return WSANO_RECOVERY;
+                }
 
-    return result;
-}
+                memmove(ServiceDBData, ThisLine, LineLen);
 
-#define SKIPWS(ptr, act) \
-{while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
+                if (!ReadFile(ServicesFile,
+                              ServiceDBData + LineLen,
+                              sizeof( ServiceDBData )-1 - LineLen,
+                              &ReadSize,
+                              NULL))
+                {
+                    break;
+                }
 
-#define SKIPANDMARKSTR(ptr, act) \
-{while(*ptr && !isspace(*ptr)) ptr++; \
- if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
+                EndValid = ServiceDBData + LineLen + ReadSize;
+                NextLine = ServiceDBData + LineLen;
+                ThisLine = ServiceDBData;
 
-static
-BOOL
-DecodeServEntFromString(IN PCHAR ServiceString,
-                        OUT PCHAR *ServiceName,
-                        OUT PCHAR *PortNumberStr,
-                        OUT PCHAR *ProtocolStr,
-                        IN PCHAR *Aliases,
-                        IN DWORD MaxAlias)
-{
-    UINT NAliases = 0;
+                if (!ReadSize) break;
+            }
+        }
 
-    //WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
+        *NextLine = '\0';
+        Comment = strchr(ThisLine, '#');
 
-    SKIPWS(ServiceString, return FALSE);
-    *ServiceName = ServiceString;
-    SKIPANDMARKSTR(ServiceString, return FALSE);
-    SKIPWS(ServiceString, return FALSE);
-    *PortNumberStr = ServiceString;
-    SKIPANDMARKSTR(ServiceString, ;);
+        if (Comment)
+            *Comment = '\0'; /* Terminate at comment start */
 
-    while (*ServiceString && NAliases < MaxAlias - 1)
-    {
-        SKIPWS(ServiceString, break);
-        if (*ServiceString)
+        if (DecodeServEntFromString(ThisLine,
+                                    &ServiceName,
+                                    &PortNumberStr,
+                                    &ProtocolStr,
+                                    Aliases,
+                                    WS2_INTERNAL_MAX_ALIAS) &&
+            (strlen(nameProtoA) == 0 || strcmp(ProtocolStr, nameProtoA) == 0))
         {
-            SKIPWS(ServiceString, ;);
-            if (strlen(ServiceString))
+            Found = (strcmp(ServiceName, nameServiceA) == 0 || strcmp(PortNumberStr, nameServiceA) == 0);
+            AliasPtr = Aliases;
+            while ((!Found) && (*AliasPtr != NULL))
             {
-                //WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
-                *Aliases++ = ServiceString;
-                NAliases++;
+                Found = (strcmp(*AliasPtr, nameServiceA) == 0);
+                AliasPtr++;
             }
-            SKIPANDMARKSTR(ServiceString, ;);
+            if (Found)
+                break;
         }
+        NextLine++;
+        ThisLine = NextLine;
     }
-    *Aliases = NULL;
 
-    *ProtocolStr = strchr(*PortNumberStr, '/');
-
-    if (!*ProtocolStr)
-        return FALSE;
-
-    **ProtocolStr = 0;
-    (*ProtocolStr)++;
+    /* This we'll do no matter what */
+    CloseHandle(ServicesFile);
 
-    //WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
-    //           *ServiceName, *ProtocolStr, *PortNumberStr,
-    //            NAliases));
+    if (!Found)
+    {
+        ERR("NSP_GetServiceByNameHeapAllocW service not found\n");
+        return WSANO_DATA;
+    }
 
-    return TRUE;
-}
+    hostinfo->addr4 = 0;
+    hostinfo->servnameW = StrA2WHeapAlloc(hHeap, ServiceName);
+    hostinfo->servprotoW = StrA2WHeapAlloc(hHeap, ProtocolStr);
+    hostinfo->servaliasesA = StrAryCpyHeapAllocA(hHeap, (char**)&Aliases);
+    hostinfo->servport = atoi(PortNumberStr);
 
-HANDLE
-WSAAPI
-OpenNetworkDatabase(_In_ LPCWSTR Name)
-{
-    PWSTR ExpandedPath;
-    PWSTR DatabasePath;
-    INT ErrorCode;
-    HKEY DatabaseKey;
-    DWORD RegType;
-    DWORD RegSize = 0;
-    size_t StringLength;
-    HANDLE Handle;
+    res = NO_ERROR;
 
-    TRACE("OpenNetworkDatabase %p\n", Name);
-    ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
-    if (!ExpandedPath)
-        return INVALID_HANDLE_VALUE;
+End:
+    if (nameA)
+        HeapFree(hHeap, 0, nameA);
 
-    /* Open the database path key */
-    ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                             L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
-                             0,
-                             KEY_READ,
-                             &DatabaseKey);
-    if (ErrorCode == NO_ERROR)
-    {
-        TRACE("OpenNetworkDatabase registry key for network database exist\n");
-        /* Read the actual path */
-        ErrorCode = RegQueryValueEx(DatabaseKey,
-                                    L"DatabasePath",
-                                    NULL,
-                                    &RegType,
-                                    NULL,
-                                    &RegSize);
+    if (nameServiceA)
+        HeapFree(hHeap, 0, nameServiceA);
 
-        if (!RegSize)
-        {
-            ERR("OpenNetworkDatabase RegQueryValueEx failed to return size for DatabasePath %lx\n", ErrorCode);
-            RegCloseKey(DatabaseKey);
-            HeapFree(GetProcessHeap(), 0, ExpandedPath);
-            return INVALID_HANDLE_VALUE;
-        }
-        DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
-        if (!DatabasePath)
-        {
-            ERR("OpenNetworkDatabase could not allocate %d for DatabasePath\n", RegSize);
-            RegCloseKey(DatabaseKey);
-            HeapFree(GetProcessHeap(), 0, ExpandedPath);
-            return INVALID_HANDLE_VALUE;
-        }
+    return res;
+}
 
-        /* Read the actual path */
-        ErrorCode = RegQueryValueEx(DatabaseKey,
-                                    L"DatabasePath",
-                                    NULL,
-                                    &RegType,
-                                    (LPBYTE)DatabasePath,
-                                    &RegSize);
+INT
+NSP_LookupServiceNextW(_In_ PWSHANDLEINTERN data,
+                       _In_ DWORD dwControlFlags,
+                       _Inout_ LPWSAQUERYSETW lpRes,
+                       _Inout_ LPDWORD lpResLen)
+{
+    MSW_BUFFER buf;
+    WSHOSTINFOINTERN hostinfo;
+    INT result;
+    HANDLE hHeap = GetProcessHeap();
+    WCHAR* ServiceInstanceNameW = NULL;
+    /* cleanup-vars */
+    CHAR* ServiceInstanceNameA = NULL;
+    CHAR* ServiceProtocolNameA = NULL;
 
-        /* Close the key */
-        RegCloseKey(DatabaseKey);
+    TRACE("NSP_LookupServiceNextW %p %lx %p %p\n", data, dwControlFlags, lpRes, lpResLen);
+    if (!data || (dwControlFlags & (~(DWORD)LUP_FLUSHPREVIOUS)) != 0 || !lpRes || !lpResLen || *lpResLen == 0)
+        return WSAEINVAL;
+    RtlZeroMemory(&hostinfo, sizeof(hostinfo));
 
-        if (ErrorCode)
-        {
-            ERR("OpenNetworkDatabase RegQueryValueEx failed to return value for DatabasePath %lx\n", ErrorCode);
-            HeapFree(GetProcessHeap(), 0, DatabasePath);
-            HeapFree(GetProcessHeap(), 0, ExpandedPath);
-            return INVALID_HANDLE_VALUE;
-        }
+    /* init and build result-buffer */
+    mswBufferInit(&buf, (BYTE*)lpRes, *lpResLen);
+    mswBufferIncUsed(&buf, sizeof(*lpRes));
 
-        /* Expand the name */
-        ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
+    /* QueryDataSet-Size without "blob-data"-size! */
+    lpRes->dwSize = sizeof(*lpRes);
+    lpRes->dwNameSpace = NS_DNS;
 
-        HeapFree(GetProcessHeap(), 0, DatabasePath);
-    }
-    else
+    if ((data->CallID == NSP_CALLID_HOSTNAME) ||
+        (data->CallID == NSP_CALLID_HOSTBYNAME) ||
+        (data->CallID == NSP_CALLID_SERVICEBYNAME))
     {
-        TRACE("OpenNetworkDatabase registry key for network database doesn't exist\n");
-        /* Use defalt path */
-        GetSystemDirectory(ExpandedPath, MAX_PATH);
-        StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
-        if (ExpandedPath[StringLength - 1] != L'\\')
+        /* FIXME remember what was returned and continue from there */
+        if (data->CallIDCounter >= 1)
         {
-            /* It isn't, so add it ourselves */
-            StringCchCat(ExpandedPath, MAX_PATH, L"\\");
+            ERR("NSP_LookupServiceNextW LUP_FLUSHPREVIOUS and more than one call not supported yet\n", data, dwControlFlags, lpRes, lpResLen);
+            result = WSA_E_NO_MORE;
+            goto End;
         }
-        StringCchCat(ExpandedPath, MAX_PATH, L"DRIVERS\\ETC\\");
-    }
-
-    /* Make sure that the path is backslash-terminated */
-    StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
-    if (ExpandedPath[StringLength - 1] != L'\\')
-    {
-        /* It isn't, so add it ourselves */
-        StringCchCat(ExpandedPath, MAX_PATH, L"\\");
     }
-
-    /* Add the database name */
-    StringCchCat(ExpandedPath, MAX_PATH, Name);
-
-    /* Return a handle to the file */
-    Handle = CreateFile(ExpandedPath,
-                        FILE_READ_DATA,
-                        FILE_SHARE_READ,
-                        NULL,
-                        OPEN_EXISTING,
-                        FILE_ATTRIBUTE_NORMAL,
-                        NULL);
-
-    HeapFree(GetProcessHeap(), 0, ExpandedPath);
-    return Handle;
-}
-
-INT
-NSP_GetServiceByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
-                               _In_ DWORD dwControlFlags,
-                               _Out_ PWSHOSTINFOINTERN hostinfo)
-{
-    BOOL Found = FALSE;
-    HANDLE ServicesFile;
-    CHAR ServiceDBData[BUFSIZ * sizeof(WCHAR)] = { 0 };
-    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
-    ProtocolStr = 0, Comment = 0, EndValid;
-    PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
-    PCHAR* AliasPtr;
-    UINT i = 0;
-    DWORD ReadSize = 0;
-    HANDLE hHeap;
-    PCHAR nameA = NULL;
-    PCHAR nameServiceA = NULL;
-    PCHAR nameProtoA = NULL;
-    INT res = WSANO_RECOVERY;
-    
-    TRACE("NSP_GetServiceByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
-    if (!data->hostnameW)
+    else
     {
-        ERR("NSP_GetServiceByNameHeapAllocW service name not provided\n");
-        res = WSANO_RECOVERY;
+        ERR("NSP_LookupServiceNextW unsupported CallID %lx\n", data->CallID);
+        result = WSAEOPNOTSUPP;
         goto End;
     }
+    data->CallIDCounter++;
 
-    hHeap = GetProcessHeap();
-    nameA = StrW2AHeapAlloc(hHeap, data->hostnameW);
-
-    /* nameA has the form <service-name>/<protocol>
-       we split these now */
-    nameProtoA = strchr(nameA, '/');
-    if (nameProtoA == NULL)
+    if (data->CallID == NSP_CALLID_HOSTNAME)
     {
-        ERR("NSP_GetServiceByNameHeapAllocW invalid service name %s\n", nameA);
-        res = WSANO_RECOVERY;
-        goto End;
-    }
+        result = NSP_GetHostNameHeapAllocW(&hostinfo.hostnameW);
 
-    nameProtoA++;
-    i = (DWORD)(nameProtoA - nameA - 1);
-    nameServiceA = (PCHAR)HeapAlloc(hHeap, 0, i + 1);
-    StringCbCopyA(nameServiceA, i + 1, nameA);
-    nameServiceA[i] = '\0';
+        if (result != ERROR_SUCCESS)
+            goto End;
 
-    ServicesFile = OpenNetworkDatabase(L"services");
-    if (ServicesFile == INVALID_HANDLE_VALUE)
+        hostinfo.addr4 = 0;
+    }
+    else if (data->CallID == NSP_CALLID_HOSTBYNAME)
     {
-        ERR("NSP_GetServiceByNameHeapAllocW unable to open services file\n");
-        return WSANO_RECOVERY;
+        result = NSP_GetHostByNameHeapAllocW(data,
+                                             dwControlFlags,
+                                             &hostinfo);
+        if (result != ERROR_SUCCESS)
+            goto End;
     }
-
-    /* Scan the services file ...
-    *
-    * We will be share the buffer on the lines. If the line does not fit in
-    * the buffer, then moving it to the beginning of the buffer and read
-    * the remnants of line from file.
-    */
-
-    /* Initial Read */
-    if (!ReadFile(ServicesFile,
-                  ServiceDBData,
-                  sizeof( ServiceDBData ) - 1,
-                  &ReadSize,
-                  NULL))
+    else
     {
-        ERR("NSP_GetServiceByNameHeapAllocW can't read services file %lx\n", GetLastError());
-        CloseHandle(ServicesFile);
-        return WSANO_RECOVERY;
+        //ASSERT(data->CallID == NSP_CALLID_SERVICEBYNAME);
+        result = NSP_GetServiceByNameHeapAllocW(data,
+                                                dwControlFlags,
+                                                &hostinfo);
+        if (result != ERROR_SUCCESS)
+            goto End;
     }
 
-    ThisLine = NextLine = ServiceDBData;
-    EndValid = ServiceDBData + ReadSize;
-    ServiceDBData[sizeof(ServiceDBData) - 1] = '\0';
-
-    while (ReadSize)
-    {
-        for (; *NextLine != '\r' && *NextLine != '\n'; NextLine++)
-        {
-            if (NextLine == EndValid)
-            {
-                int LineLen = NextLine - ThisLine;
-
-                if (ThisLine == ServiceDBData)
-                {
-                    ERR("NSP_GetServiceByNameHeapAllocW line too long\n");
-                    CloseHandle(ServicesFile);
-                    return WSANO_RECOVERY;
-                }
-
-                memmove(ServiceDBData, ThisLine, LineLen);
-
-                if (!ReadFile(ServicesFile,
-                              ServiceDBData + LineLen,
-                              sizeof( ServiceDBData )-1 - LineLen,
-                              &ReadSize,
-                              NULL))
-                {
-                    break;
-                }
-
-                EndValid = ServiceDBData + LineLen + ReadSize;
-                NextLine = ServiceDBData + LineLen;
-                ThisLine = ServiceDBData;
-
-                if (!ReadSize) break;
-            }
-        }
-
-        *NextLine = '\0';
-        Comment = strchr(ThisLine, '#');
-
-        if (Comment)
-            *Comment = '\0'; /* Terminate at comment start */
-
-        if (DecodeServEntFromString(ThisLine,
-                                    &ServiceName,
-                                    &PortNumberStr,
-                                    &ProtocolStr,
-                                    Aliases,
-                                    WS2_INTERNAL_MAX_ALIAS) &&
-            (strlen(nameProtoA) == 0 || strcmp(ProtocolStr, nameProtoA) == 0))
-        {
-            Found = (strcmp(ServiceName, nameServiceA) == 0 || strcmp(PortNumberStr, nameServiceA) == 0);
-            AliasPtr = Aliases;
-            while ((!Found) && (*AliasPtr != NULL))
-            {
-                Found = (strcmp(*AliasPtr, nameServiceA) == 0);
-                AliasPtr++;
-            }
-            if (Found)
-                break;
-        }
-        NextLine++;
-        ThisLine = NextLine;
-    }
-
-    /* This we'll do no matter what */
-    CloseHandle(ServicesFile);
-
-    if (!Found)
-    {
-        ERR("NSP_GetServiceByNameHeapAllocW service not found\n");
-        return WSANO_DATA;
-    }
-
-    hostinfo->addr4 = 0;
-    hostinfo->servnameW = StrA2WHeapAlloc(hHeap, ServiceName);
-    hostinfo->servprotoW = StrA2WHeapAlloc(hHeap, ProtocolStr);
-    hostinfo->servaliasesA = StrAryCpyHeapAllocA(hHeap, (char**)&Aliases);
-    hostinfo->servport = atoi(PortNumberStr);
-
-    res = NO_ERROR;
-
-End:
-    if (nameA)
-        HeapFree(hHeap, 0, nameA);
-
-    if (nameServiceA)
-        HeapFree(hHeap, 0, nameServiceA);
-
-    return res;
-}
-
-INT
-NSP_LookupServiceNextW(_In_ PWSHANDLEINTERN data,
-                       _In_ DWORD dwControlFlags,
-                       _Inout_ LPWSAQUERYSETW lpRes,
-                       _Inout_ LPDWORD lpResLen)
-{
-    MSW_BUFFER buf;
-    WSHOSTINFOINTERN hostinfo;
-    INT result;
-    HANDLE hHeap = GetProcessHeap();
-    WCHAR* ServiceInstanceNameW = NULL;
-    /* cleanup-vars */
-    CHAR* ServiceInstanceNameA = NULL;
-    CHAR* ServiceProtocolNameA = NULL;
-
-    TRACE("NSP_LookupServiceNextW %p %lx %p %p\n", data, dwControlFlags, lpRes, lpResLen);
-    if (!data || (dwControlFlags & (~(DWORD)LUP_FLUSHPREVIOUS)) != 0 || !lpRes || !lpResLen || *lpResLen == 0)
-        return WSAEINVAL;
-    RtlZeroMemory(&hostinfo, sizeof(hostinfo));
-
-    /* init and build result-buffer */
-    mswBufferInit(&buf, (BYTE*)lpRes, *lpResLen);
-    mswBufferIncUsed(&buf, sizeof(*lpRes));
-
-    /* QueryDataSet-Size without "blob-data"-size! */
-    lpRes->dwSize = sizeof(*lpRes);
-    lpRes->dwNameSpace = NS_DNS;
-
-    if ((data->CallID == NSP_CALLID_HOSTNAME) ||
-        (data->CallID == NSP_CALLID_HOSTBYNAME) ||
-        (data->CallID == NSP_CALLID_SERVICEBYNAME))
-    {
-        /* FIXME remember what was returned and continue from there */
-        if (data->CallIDCounter >= 1)
-        {
-            ERR("NSP_LookupServiceNextW LUP_FLUSHPREVIOUS and more than one call not supported yet\n", data, dwControlFlags, lpRes, lpResLen);
-            result = WSA_E_NO_MORE;
-            goto End;
-        }
-    }
-    else
-    {
-        ERR("NSP_LookupServiceNextW unsupported CallID %lx\n", data->CallID);
-        result = WSAEOPNOTSUPP;
-        goto End;
-    }
-    data->CallIDCounter++;
-
-    if (data->CallID == NSP_CALLID_HOSTNAME)
-    {
-        result = NSP_GetHostNameHeapAllocW(&hostinfo.hostnameW);
-
-        if (result != ERROR_SUCCESS)
-            goto End;
-
-        hostinfo.addr4 = 0;
-    }
-    else if (data->CallID == NSP_CALLID_HOSTBYNAME)
-    {
-        result = NSP_GetHostByNameHeapAllocW(data,
-                                             dwControlFlags,
-                                             &hostinfo);
-        if (result != ERROR_SUCCESS)
-            goto End;
-    }
-    else
-    {
-        //ASSERT(data->CallID == NSP_CALLID_SERVICEBYNAME);
-        result = NSP_GetServiceByNameHeapAllocW(data,
-                                                dwControlFlags,
-                                                &hostinfo);
-        if (result != ERROR_SUCCESS)
-            goto End;
-    }
-
-    if (((LUP_RETURN_BLOB & data->dwControlFlags) != 0) ||
-        ((LUP_RETURN_NAME & data->dwControlFlags) != 0))
+    if (((LUP_RETURN_BLOB & data->dwControlFlags) != 0) ||
+        ((LUP_RETURN_NAME & data->dwControlFlags) != 0))
     {
         if (data->CallID == NSP_CALLID_HOSTNAME || data->CallID == NSP_CALLID_HOSTBYNAME)
         {
@@ -1117,6 +793,289 @@ End:
     return result;
 }
 
+INT
+WSAAPI
+mwsNSPCleanUp(_In_ LPGUID lpProviderId)
+{
+    return ERROR_SUCCESS;
+}
+
+INT
+mwsNSPInit(VOID)
+{
+    return ERROR_SUCCESS;
+}
+
+INT
+WSAAPI
+mwsNSPLookupServiceBegin(_In_ LPGUID lpProviderId,
+                         _In_ LPWSAQUERYSETW lpqsRestrictions,
+                         _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
+                         _In_ DWORD dwControlFlags,
+                         _Out_ LPHANDLE lphLookup)
+{
+    PWSHANDLEINTERN pLook;
+    int wsaErr;
+
+    TRACE("mwsNSPLookupServiceBegin %p %p %p %lx %p\n", lpProviderId, lpqsRestrictions, lpServiceClassInfo, dwControlFlags, lphLookup);
+    if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
+    {
+        //OK
+        TRACE("TCPIP query\n");
+    }
+    else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
+    {
+        ERR("NLA queries are not supported yet\n");
+        WSASetLastError(WSASERVICE_NOT_FOUND);
+        return SOCKET_ERROR;
+    }
+    else
+    {
+        ERR("Unsupported GUID\n");
+        return ERROR_CALL_NOT_IMPLEMENTED;
+    }
+
+    /* allocate internal structure */
+    pLook = HeapAlloc(GetProcessHeap(), 0, sizeof(WSHANDLEINTERN));
+    if (!pLook)
+    {
+        ERR("Error allocating %d for handle\n", sizeof(WSHANDLEINTERN));
+        WSASetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    *lphLookup = (HANDLE)pLook;
+
+    RtlZeroMemory(pLook, sizeof(*pLook));
+
+    /* Anyway the ControlFlags "should" be needed
+       in NSPLookupServiceNext. (see doku) But
+       thats not the fact ATM. */
+    pLook->dwControlFlags = dwControlFlags;
+    pLook->providerId = *lpProviderId;
+
+#ifdef NSP_REDIRECT
+
+    if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
+    {
+        pLook->rdrproc = rdrproc_tcpip;
+    }
+    else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
+    {
+        pLook->rdrproc = rdrproc_nla;
+    }
+    else
+    {
+        return ERROR_CALL_NOT_IMPLEMENTED;
+    }
+
+    if (pLook->rdrproc.NSPLookupServiceBegin(lpProviderId,
+                                             lpqsRestrictions,
+                                             lpServiceClassInfo,
+                                             dwControlFlags,
+                                             &pLook->rdrLookup) == NO_ERROR)
+    {
+        wsaErr = NO_ERROR;
+    }
+    else
+    {
+        wsaErr = WSAGetLastError();
+    }
+
+    /*
+    if (res)
+        res = WSAGetLastError();
+    */
+
+#else /* NSP_REDIRECT */
+
+    wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
+    if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_NULL))
+    {
+        ERR("NULL GUID service class is not implemented yet\n");
+        wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
+    }
+    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_HOSTNAME))
+    {
+        TRACE("HOSTNAME GUID\n");
+        wsaErr = NSP_LookupServiceBeginW(pLook,
+                                         NULL,
+                                         NULL,
+                                         NSP_CALLID_HOSTNAME);
+    }
+    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
+                         &guid_INET_HOSTADDRBYNAME))
+    {
+        TRACE("INET_HOSTADDRBYNAME GUID\n");
+        wsaErr = NSP_LookupServiceBeginW(pLook,
+                                         NULL,
+                                         lpqsRestrictions->lpszServiceInstanceName,
+                                         NSP_CALLID_HOSTBYNAME);
+    }
+    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
+                         &guid_INET_SERVICEBYNAME))
+    {
+        TRACE("INET_SERVICEBYNAME\n");
+        wsaErr = NSP_LookupServiceBeginW(pLook,
+                                         NULL,
+                                         lpqsRestrictions->lpszServiceInstanceName,
+                                         NSP_CALLID_SERVICEBYNAME);
+    }
+    else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
+                         &guid_INET_HOSTADDRBYINETSTRING))
+    {
+        ERR("INET_HOSTADDRBYINETSTRING GUID service class is not implemented yet\n");
+        wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
+    }
+
+#endif /* NSP_REDIRECT */
+
+    if (wsaErr != NO_ERROR)
+    {
+        ERR("mwsNSPLookupServiceBegin wsaErr = %d\n", wsaErr);
+        WSASetLastError(wsaErr);
+        return SOCKET_ERROR;
+    }
+    return NO_ERROR;
+}
+
+INT
+WSAAPI
+mwsNSPLookupServiceNext(_In_ HANDLE hLookup,
+                        _In_ DWORD dwControlFlags,
+                        _Inout_ LPDWORD lpdwBufferLength,
+                        //_Out_writes_bytes_to_(*lpdwBufferLength, *lpdwBufferLength)
+                        LPWSAQUERYSETW lpqsResults)
+{
+    PWSHANDLEINTERN pLook = hLookup;
+    int wsaErr = 0;
+
+    TRACE("mwsNSPLookupServiceNext %p %lx %p %p\n", pLook, dwControlFlags, lpdwBufferLength, lpqsResults);
+#ifdef NSP_REDIRECT
+
+    INT res = pLook->rdrproc.NSPLookupServiceNext(pLook->rdrLookup,
+                                                  dwControlFlags,
+                                                  lpdwBufferLength,
+                                                  lpqsResults);
+    wsaErr = WSAGetLastError();
+    if (res != ERROR_SUCCESS)
+    {
+        wsaErr = WSAGetLastError();
+
+        if (wsaErr == 0)
+            wsaErr = 0xFFFFFFFF;
+    }
+
+#else /* NSP_REDIRECT */
+
+    if ((lpdwBufferLength == NULL) || (*lpdwBufferLength == 0))
+    {
+        wsaErr = WSA_NOT_ENOUGH_MEMORY;
+        goto End;
+    }
+
+    RtlZeroMemory(lpqsResults, *lpdwBufferLength);
+    lpqsResults->dwSize = sizeof(*lpqsResults);
+
+    wsaErr = NSP_LookupServiceNextW(pLook,
+                                    dwControlFlags,
+                                    lpqsResults,
+                                    lpdwBufferLength);
+
+
+#endif /* NSP_REDIRECT */
+
+End:
+    if (wsaErr != 0)
+    {
+        ERR("mwsNSPLookupServiceNext wsaErr = %d\n", wsaErr);
+        WSASetLastError(wsaErr);
+        return SOCKET_ERROR;
+    }
+    return NO_ERROR;
+}
+
+INT
+WSAAPI
+mwsNSPIoCtl(_In_ HANDLE hLookup,
+            _In_ DWORD dwControlCode,
+            _In_reads_bytes_(cbInBuffer) LPVOID lpvInBuffer,
+            _In_ DWORD cbInBuffer,
+            _Out_writes_bytes_to_(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer,
+            _In_ DWORD cbOutBuffer,
+            _Out_ LPDWORD lpcbBytesReturned,
+            _In_opt_ LPWSACOMPLETION lpCompletion,
+            _In_ LPWSATHREADID lpThreadId)
+{
+    ERR("mwsNSPIoCtl not implemented %p %lx %p %ld %p %ld %p %p %p\n", hLookup, dwControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpCompletion, lpThreadId);
+    WSASetLastError(WSAEOPNOTSUPP);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+INT
+WSAAPI
+mwsNSPLookupServiceEnd(_In_ HANDLE hLookup)
+{
+    PWSHANDLEINTERN pLook = (PWSHANDLEINTERN)hLookup;
+    HANDLE hHeap = GetProcessHeap();
+    INT res = NO_ERROR;
+
+    TRACE("mwsNSPLookupServiceEnd %p\n", pLook);
+#ifdef NSP_REDIRECT
+    res = pLook->rdrproc.NSPLookupServiceEnd(pLook->rdrLookup);
+#endif
+
+    if (pLook->hostnameW != NULL)
+        HeapFree(hHeap, 0, pLook->hostnameW);
+
+    HeapFree(hHeap, 0, pLook);
+    return res;
+}
+
+INT
+WSAAPI
+mwsNSPSetService(_In_ LPGUID lpProviderId,
+                 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
+                 _In_ LPWSAQUERYSETW lpqsRegInfo,
+                 _In_ WSAESETSERVICEOP essOperation,
+                 _In_ DWORD dwControlFlags)
+{
+    ERR("mwsNSPSetService not implemented %p %p %p %d %lx %ld %p %p %p\n", lpProviderId, lpServiceClassInfo, lpqsRegInfo, essOperation, dwControlFlags);
+    WSASetLastError(WSAEOPNOTSUPP);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+INT
+WSAAPI
+mwsNSPInstallServiceClass(_In_ LPGUID lpProviderId,
+                          _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+    ERR("mwsNSPInstallServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassInfo);
+    WSASetLastError(WSAEOPNOTSUPP);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+INT
+WSAAPI
+mwsNSPRemoveServiceClass(_In_ LPGUID lpProviderId,
+                         _In_ LPGUID lpServiceClassId)
+{
+    ERR("mwsNSPRemoveServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassId);
+    WSASetLastError(WSAEOPNOTSUPP);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+INT
+WSAAPI
+mwsNSPGetServiceClassInfo(_In_ LPGUID lpProviderId,
+                          _In_ LPDWORD lpdwBufSize,
+                          _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+    ERR("mwsNSPGetServiceClassInfo not implemented %p %p %p\n", lpProviderId, lpdwBufSize, lpServiceClassInfo);
+    WSASetLastError(WSAEOPNOTSUPP);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
 /* Implementations - Exports */
 /*
  * @implemented