15 #include "mswhelper.h"
17 #include <wine/debug.h>
18 WINE_DEFAULT_DEBUG_CHANNEL(mswsock
);
20 #define NSP_CALLID_DNS 0x0001
21 #define NSP_CALLID_HOSTNAME 0x0002
22 #define NSP_CALLID_HOSTBYNAME 0x0003
23 #define NSP_CALLID_SERVICEBYNAME 0x0004
28 #ifndef WS2_INTERNAL_MAX_ALIAS
29 #define WS2_INTERNAL_MAX_ALIAS 512
30 #endif // WS2_INTERNAL_MAX_ALIAS
32 //#define IP_LOCALHOST 0x0100007F
34 //#define NSP_REDIRECT
41 CHAR
** servaliasesA
; /* array */
43 } WSHOSTINFOINTERN
, *PWSHOSTINFOINTERN
;
46 GUID providerId
; /* Provider-ID */
47 DWORD dwControlFlags
; /* dwControlFlags (WSALookupServiceBegin) */
48 DWORD CallID
; /* List for LookupServiceNext-Calls */
49 DWORD CallIDCounter
; /* call-count of the current CallID. */
50 WCHAR
* hostnameW
; /* hostbyname */
55 } WSHANDLEINTERN
, *PWSHANDLEINTERN
;
57 static const GUID guid_NULL
= {0};
58 static const GUID guid_HOSTNAME
= SVCID_HOSTNAME
;
59 static const GUID guid_INET_HOSTADDRBYINETSTRING
= SVCID_INET_HOSTADDRBYINETSTRING
;
60 static const GUID guid_INET_HOSTADDRBYNAME
= SVCID_INET_HOSTADDRBYNAME
;
61 static const GUID guid_INET_SERVICEBYNAME
= SVCID_INET_SERVICEBYNAME
;
63 /* GUIDs - maybe they should be loaded from registry? */
65 static const GUID guid_mswsock_TcpIp
= {/*Data1:*/ 0x22059D40,
68 /*Data4:*/ {0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B}};
70 /* {6642243A-3BA8-4AA6-BAA5-2E0BD71FDD83} */
72 static const GUID guid_mswsock_NLA
= {/*Data1:*/ 0x6642243A,
75 /*Data4:*/ {0xBA, 0xA5, 0x2E, 0x0B, 0xD7, 0x1F, 0xDD, 0x83}};
80 (CALLBACK
*lpRdrNSPStartup
)(
82 LPNSP_ROUTINE lpRout
);
84 const rdrLib
= "mswsock.dll-original";
85 lpRdrNSPStartup rdrNSPStartup
;
87 NSP_ROUTINE rdrproc_tcpip
;
88 NSP_ROUTINE rdrproc_nla
;
90 #endif /* NSP_REDIRECT */
97 LPNSP_ROUTINE lpRout
);
100 NSP_LookupServiceBeginW(
101 PWSHANDLEINTERN data
,
107 NSP_LookupServiceNextW(
108 _In_ PWSHANDLEINTERN data
,
109 _In_ DWORD dwControlFlags
,
110 _Inout_ LPWSAQUERYSETW lpRes
,
111 _Inout_ LPDWORD lpResLen
);
114 NSP_GetHostNameHeapAllocW(
115 _Out_ WCHAR
** hostname
);
118 NSP_GetHostByNameHeapAllocW(
119 _In_ PWSHANDLEINTERN data
,
120 _In_ DWORD dwControlFlags
,
121 _Out_ PWSHOSTINFOINTERN hostinfo
);
124 NSP_GetServiceByNameHeapAllocW(
125 _In_ PWSHANDLEINTERN data
,
126 _In_ DWORD dwControlFlags
,
127 _Out_ PWSHOSTINFOINTERN hostinfo
);
129 /* Implementations - Internal */
133 mwsNSPCleanUp(_In_ LPGUID lpProviderId
)
135 //WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
136 //return ERROR_CALL_NOT_IMPLEMENTED;
137 return ERROR_SUCCESS
;
143 return ERROR_SUCCESS
;
148 mwsNSPLookupServiceBegin(_In_ LPGUID lpProviderId
,
149 _In_ LPWSAQUERYSETW lpqsRestrictions
,
150 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo
,
151 _In_ DWORD dwControlFlags
,
152 _Out_ LPHANDLE lphLookup
)
154 PWSHANDLEINTERN pLook
;
157 TRACE("mwsNSPLookupServiceBegin %p %p %p %lx %p\n", lpProviderId
, lpqsRestrictions
, lpServiceClassInfo
, dwControlFlags
, lphLookup
);
158 if (IsEqualGUID(lpProviderId
, &guid_mswsock_TcpIp
))
161 TRACE("TCPIP query\n");
163 else if (IsEqualGUID(lpProviderId
, &guid_mswsock_NLA
))
165 ERR("NLA queries are not supported yet\n");
166 WSASetLastError(WSASERVICE_NOT_FOUND
);
171 ERR("Unsupported GUID\n");
172 return ERROR_CALL_NOT_IMPLEMENTED
;
175 /* allocate internal structure */
176 pLook
= HeapAlloc(GetProcessHeap(), 0, sizeof(WSHANDLEINTERN
));
179 ERR("Error allocating %d for handle\n", sizeof(WSHANDLEINTERN
));
180 WSASetLastError(WSAEFAULT
);
184 *lphLookup
= (HANDLE
)pLook
;
186 RtlZeroMemory(pLook
, sizeof(*pLook
));
188 /* Anyway the ControlFlags "should" be needed
189 in NSPLookupServiceNext. (see doku) But
190 thats not the fact ATM. */
191 pLook
->dwControlFlags
= dwControlFlags
;
192 pLook
->providerId
= *lpProviderId
;
196 if (IsEqualGUID(lpProviderId
, &guid_mswsock_TcpIp
))
198 pLook
->rdrproc
= rdrproc_tcpip
;
200 else if (IsEqualGUID(lpProviderId
, &guid_mswsock_NLA
))
202 pLook
->rdrproc
= rdrproc_nla
;
206 return ERROR_CALL_NOT_IMPLEMENTED
;
209 if (pLook
->rdrproc
.NSPLookupServiceBegin(lpProviderId
,
213 &pLook
->rdrLookup
) == NO_ERROR
)
219 wsaErr
= WSAGetLastError();
224 res = WSAGetLastError();
227 #else /* NSP_REDIRECT */
229 wsaErr
= ERROR_CALL_NOT_IMPLEMENTED
;
230 if (IsEqualGUID(lpqsRestrictions
->lpServiceClassId
, &guid_NULL
))
232 ERR("NULL GUID service class is not implemented yet\n");
233 wsaErr
= ERROR_CALL_NOT_IMPLEMENTED
;
235 else if (IsEqualGUID(lpqsRestrictions
->lpServiceClassId
, &guid_HOSTNAME
))
237 TRACE("HOSTNAME GUID\n");
238 wsaErr
= NSP_LookupServiceBeginW(pLook
,
241 NSP_CALLID_HOSTNAME
);
243 else if (IsEqualGUID(lpqsRestrictions
->lpServiceClassId
,
244 &guid_INET_HOSTADDRBYNAME
))
246 TRACE("INET_HOSTADDRBYNAME GUID\n");
247 wsaErr
= NSP_LookupServiceBeginW(pLook
,
249 lpqsRestrictions
->lpszServiceInstanceName
,
250 NSP_CALLID_HOSTBYNAME
);
252 else if (IsEqualGUID(lpqsRestrictions
->lpServiceClassId
,
253 &guid_INET_SERVICEBYNAME
))
255 TRACE("INET_SERVICEBYNAME\n");
256 wsaErr
= NSP_LookupServiceBeginW(pLook
,
258 lpqsRestrictions
->lpszServiceInstanceName
,
259 NSP_CALLID_SERVICEBYNAME
);
261 else if (IsEqualGUID(lpqsRestrictions
->lpServiceClassId
,
262 &guid_INET_HOSTADDRBYINETSTRING
))
264 ERR("INET_HOSTADDRBYINETSTRING GUID service class is not implemented yet\n");
265 wsaErr
= ERROR_CALL_NOT_IMPLEMENTED
;
268 #endif /* NSP_REDIRECT */
270 if (wsaErr
!= NO_ERROR
)
272 ERR("mwsNSPLookupServiceBegin wsaErr = %d\n", wsaErr
);
273 WSASetLastError(wsaErr
);
281 mwsNSPLookupServiceNext(_In_ HANDLE hLookup
,
282 _In_ DWORD dwControlFlags
,
283 _Inout_ LPDWORD lpdwBufferLength
,
284 //_Out_writes_bytes_to_(*lpdwBufferLength, *lpdwBufferLength)
285 LPWSAQUERYSETW lpqsResults
)
287 PWSHANDLEINTERN pLook
= hLookup
;
290 TRACE("mwsNSPLookupServiceNext %p %lx %p %p\n", pLook
, dwControlFlags
, lpdwBufferLength
, lpqsResults
);
293 INT res
= pLook
->rdrproc
.NSPLookupServiceNext(pLook
->rdrLookup
,
297 wsaErr
= WSAGetLastError();
298 if (res
!= ERROR_SUCCESS
)
300 wsaErr
= WSAGetLastError();
306 #else /* NSP_REDIRECT */
308 if ((lpdwBufferLength
== NULL
) || (*lpdwBufferLength
== 0))
310 wsaErr
= WSA_NOT_ENOUGH_MEMORY
;
314 RtlZeroMemory(lpqsResults
, *lpdwBufferLength
);
315 lpqsResults
->dwSize
= sizeof(*lpqsResults
);
317 wsaErr
= NSP_LookupServiceNextW(pLook
,
323 #endif /* NSP_REDIRECT */
328 ERR("mwsNSPLookupServiceNext wsaErr = %d\n", wsaErr
);
329 WSASetLastError(wsaErr
);
337 mwsNSPIoCtl(_In_ HANDLE hLookup
,
338 _In_ DWORD dwControlCode
,
339 _In_reads_bytes_(cbInBuffer
) LPVOID lpvInBuffer
,
340 _In_ DWORD cbInBuffer
,
341 _Out_writes_bytes_to_(cbOutBuffer
, *lpcbBytesReturned
) LPVOID lpvOutBuffer
,
342 _In_ DWORD cbOutBuffer
,
343 _Out_ LPDWORD lpcbBytesReturned
,
344 _In_opt_ LPWSACOMPLETION lpCompletion
,
345 _In_ LPWSATHREADID lpThreadId
)
347 ERR("mwsNSPIoCtl not implemented %p %lx %p %ld %p %ld %p %p %p\n", hLookup
, dwControlCode
, lpvInBuffer
, cbInBuffer
, lpvOutBuffer
, cbOutBuffer
, lpcbBytesReturned
, lpCompletion
, lpThreadId
);
348 WSASetLastError(WSAEOPNOTSUPP
);
349 return ERROR_CALL_NOT_IMPLEMENTED
;
354 mwsNSPLookupServiceEnd(_In_ HANDLE hLookup
)
356 PWSHANDLEINTERN pLook
= (PWSHANDLEINTERN
)hLookup
;
357 HANDLE hHeap
= GetProcessHeap();
360 TRACE("mwsNSPLookupServiceEnd %p\n", pLook
);
362 res
= pLook
->rdrproc
.NSPLookupServiceEnd(pLook
->rdrLookup
);
365 if (pLook
->hostnameW
!= NULL
)
366 HeapFree(hHeap
, 0, pLook
->hostnameW
);
368 HeapFree(hHeap
, 0, pLook
);
374 mwsNSPSetService(_In_ LPGUID lpProviderId
,
375 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo
,
376 _In_ LPWSAQUERYSETW lpqsRegInfo
,
377 _In_ WSAESETSERVICEOP essOperation
,
378 _In_ DWORD dwControlFlags
)
380 ERR("mwsNSPSetService not implemented %p %p %p %d %lx %ld %p %p %p\n", lpProviderId
, lpServiceClassInfo
, lpqsRegInfo
, essOperation
, dwControlFlags
);
381 WSASetLastError(WSAEOPNOTSUPP
);
382 return ERROR_CALL_NOT_IMPLEMENTED
;
387 mwsNSPInstallServiceClass(_In_ LPGUID lpProviderId
,
388 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo
)
390 ERR("mwsNSPInstallServiceClass not implemented %p %p\n", lpProviderId
, lpServiceClassInfo
);
391 WSASetLastError(WSAEOPNOTSUPP
);
392 return ERROR_CALL_NOT_IMPLEMENTED
;
397 mwsNSPRemoveServiceClass(_In_ LPGUID lpProviderId
,
398 _In_ LPGUID lpServiceClassId
)
400 ERR("mwsNSPRemoveServiceClass not implemented %p %p\n", lpProviderId
, lpServiceClassId
);
401 WSASetLastError(WSAEOPNOTSUPP
);
402 return ERROR_CALL_NOT_IMPLEMENTED
;
407 mwsNSPGetServiceClassInfo(_In_ LPGUID lpProviderId
,
408 _In_ LPDWORD lpdwBufSize
,
409 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo
)
411 ERR("mwsNSPGetServiceClassInfo not implemented %p %p %p\n", lpProviderId
, lpdwBufSize
, lpServiceClassInfo
);
412 WSASetLastError(WSAEOPNOTSUPP
);
413 return ERROR_CALL_NOT_IMPLEMENTED
;
417 hostnameA / hostnameW
418 * only used by HOSTBYNAME
419 * only one should be set
423 NSP_LookupServiceBeginW(PWSHANDLEINTERN data
,
430 TRACE("NSP_LookupServiceBeginW %p %p %p %lx\n", data
, hostnameA
, hostnameW
, CallID
);
431 if (data
->CallID
!= 0)
434 data
->CallID
= CallID
;
436 if ((CallID
== NSP_CALLID_HOSTBYNAME
) ||
437 (CallID
== NSP_CALLID_SERVICEBYNAME
))
439 hHeap
= GetProcessHeap();
441 if (data
->hostnameW
!= NULL
)
442 HeapFree(hHeap
, 0, data
->hostnameW
);
444 if (hostnameA
!= NULL
)
446 data
->hostnameW
= StrA2WHeapAlloc(hHeap
, hostnameA
);
450 data
->hostnameW
= StrCpyHeapAllocW(hHeap
, hostnameW
);
455 ERR("NSP_LookupServiceBeginW unsupported CallID\n");
456 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
457 return ERROR_CALL_NOT_IMPLEMENTED
;
460 return ERROR_SUCCESS
;
464 NSP_GetHostNameHeapAllocW(_Out_ WCHAR
** hostname
)
467 HANDLE hHeap
= GetProcessHeap();
468 DWORD bufCharLen
= 0;
470 TRACE("NSP_GetHostNameHeapAllocW %p\n", hostname
);
471 /* FIXME Use DnsGetHostName_W when available */
472 GetComputerNameExW(ComputerNameDnsHostname
, NULL
, &bufCharLen
);
475 ERR("NSP_GetHostNameHeapAllocW zero size for computername returned\n");
476 WSASetLastError(WSAEFAULT
);
479 name
= HeapAlloc(hHeap
, 0, bufCharLen
*sizeof(WCHAR
));
480 if (!GetComputerNameExW(ComputerNameDnsHostname
,
484 ERR("NSP_GetHostNameHeapAllocW error obtaining computername %lx\n", GetLastError());
485 HeapFree(hHeap
, 0, name
);
486 WSASetLastError(WSAEFAULT
);
491 return ERROR_SUCCESS
;
495 NSP_GetHostByNameHeapAllocW(_In_ PWSHANDLEINTERN data
,
496 _In_ DWORD dwControlFlags
,
497 _Out_ PWSHOSTINFOINTERN hostinfo
)
499 HANDLE hHeap
= GetProcessHeap();
500 DNS_STATUS dns_status
= { 0 };
501 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
504 INT result
= ERROR_SUCCESS
;
505 DWORD dwQueryFlags
= DNS_QUERY_STANDARD
;
506 PWCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
509 TRACE("NSP_GetHostByNameHeapAllocW %p %lx %p\n", data
, dwControlFlags
, hostinfo
);
510 /* needed to be cleaned up if != NULL */
513 if (!data
->hostnameW
)
515 result
= ERROR_INVALID_PARAMETER
;
519 if ((data
->dwControlFlags
& LUP_DEEP
) == 0)
521 TRACE("NSP_GetHostByNameHeapAllocW LUP_DEEP is not specified. Disabling recursion\n");
522 dwQueryFlags
|= DNS_QUERY_NO_RECURSION
;
525 /* DNS_TYPE_A: include/WinDNS.h */
526 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
527 dns_status
= DnsQuery_W(data
->hostnameW
,
530 NULL
/* extra dns servers */,
533 if (dns_status
== ERROR_INVALID_NAME
)
535 ERR("NSP_GetHostByNameHeapAllocW invalid name\n");
536 WSASetLastError(WSAEFAULT
);
537 result
= ERROR_INVALID_PARAMETER
;
541 if ((dns_status
!= 0) || (dp
== NULL
))
543 ERR("NSP_GetHostByNameHeapAllocW not found %lx %p\n", dns_status
, dp
);
544 result
= WSAHOST_NOT_FOUND
;
548 //ASSERT(dp->wType == DNS_TYPE_A);
549 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
551 while ((curr
->pNext
!= NULL
) || (curr
->wType
!= DNS_TYPE_A
))
553 if (curr
->wType
== DNS_TYPE_CNAME
)
555 TRACE("NSP_GetHostByNameHeapAllocW found alias %ws\n", curr
->Data
.Cname
.pNameHost
);
556 Aliases
[AliasIndex
++] = curr
->Data
.Cname
.pNameHost
;
561 if (curr
->wType
!= DNS_TYPE_A
)
563 ERR("NSP_GetHostByNameHeapAllocW last record is not of type A %d\n", curr
->wType
);
564 result
= WSASERVICE_NOT_FOUND
;
567 hostinfo
->hostnameW
= StrCpyHeapAllocW(hHeap
, curr
->pName
);
568 hostinfo
->addr4
= curr
->Data
.A
.IpAddress
;
571 hostinfo
->servaliasesA
= StrAryCpyHeapAllocWToA(hHeap
, (WCHAR
**)&Aliases
);
573 result
= ERROR_SUCCESS
;
577 DnsRecordListFree(dp
, DnsFreeRecordList
);
582 #define SKIPWS(ptr, act) \
583 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
585 #define SKIPANDMARKSTR(ptr, act) \
586 {while(*ptr && !isspace(*ptr)) ptr++; \
587 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
591 DecodeServEntFromString(IN PCHAR ServiceString
,
592 OUT PCHAR
*ServiceName
,
593 OUT PCHAR
*PortNumberStr
,
594 OUT PCHAR
*ProtocolStr
,
600 //WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
602 SKIPWS(ServiceString
, return FALSE
);
603 *ServiceName
= ServiceString
;
604 SKIPANDMARKSTR(ServiceString
, return FALSE
);
605 SKIPWS(ServiceString
, return FALSE
);
606 *PortNumberStr
= ServiceString
;
607 SKIPANDMARKSTR(ServiceString
, ;);
609 while (*ServiceString
&& NAliases
< MaxAlias
- 1)
611 SKIPWS(ServiceString
, break);
614 SKIPWS(ServiceString
, ;);
615 if (strlen(ServiceString
))
617 //WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
618 *Aliases
++ = ServiceString
;
621 SKIPANDMARKSTR(ServiceString
, ;);
626 *ProtocolStr
= strchr(*PortNumberStr
, '/');
634 //WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
635 // *ServiceName, *ProtocolStr, *PortNumberStr,
643 OpenNetworkDatabase(_In_ LPCWSTR Name
)
654 TRACE("OpenNetworkDatabase %p\n", Name
);
655 ExpandedPath
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
*sizeof(WCHAR
));
657 return INVALID_HANDLE_VALUE
;
659 /* Open the database path key */
660 ErrorCode
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
661 L
"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
665 if (ErrorCode
== NO_ERROR
)
667 TRACE("OpenNetworkDatabase registry key for network database exist\n");
668 /* Read the actual path */
669 ErrorCode
= RegQueryValueEx(DatabaseKey
,
678 ERR("OpenNetworkDatabase RegQueryValueEx failed to return size for DatabasePath %lx\n", ErrorCode
);
679 RegCloseKey(DatabaseKey
);
680 HeapFree(GetProcessHeap(), 0, ExpandedPath
);
681 return INVALID_HANDLE_VALUE
;
683 DatabasePath
= HeapAlloc(GetProcessHeap(), 0, RegSize
);
686 ERR("OpenNetworkDatabase could not allocate %d for DatabasePath\n", RegSize
);
687 RegCloseKey(DatabaseKey
);
688 HeapFree(GetProcessHeap(), 0, ExpandedPath
);
689 return INVALID_HANDLE_VALUE
;
692 /* Read the actual path */
693 ErrorCode
= RegQueryValueEx(DatabaseKey
,
697 (LPBYTE
)DatabasePath
,
701 RegCloseKey(DatabaseKey
);
705 ERR("OpenNetworkDatabase RegQueryValueEx failed to return value for DatabasePath %lx\n", ErrorCode
);
706 HeapFree(GetProcessHeap(), 0, DatabasePath
);
707 HeapFree(GetProcessHeap(), 0, ExpandedPath
);
708 return INVALID_HANDLE_VALUE
;
711 /* Expand the name */
712 ExpandEnvironmentStrings(DatabasePath
, ExpandedPath
, MAX_PATH
);
714 HeapFree(GetProcessHeap(), 0, DatabasePath
);
718 TRACE("OpenNetworkDatabase registry key for network database doesn't exist\n");
719 /* Use defalt path */
720 GetSystemDirectory(ExpandedPath
, MAX_PATH
);
721 StringCchLength(ExpandedPath
, MAX_PATH
, &StringLength
);
722 if (ExpandedPath
[StringLength
- 1] != L
'\\')
724 /* It isn't, so add it ourselves */
725 StringCchCat(ExpandedPath
, MAX_PATH
, L
"\\");
727 StringCchCat(ExpandedPath
, MAX_PATH
, L
"DRIVERS\\ETC\\");
730 /* Make sure that the path is backslash-terminated */
731 StringCchLength(ExpandedPath
, MAX_PATH
, &StringLength
);
732 if (ExpandedPath
[StringLength
- 1] != L
'\\')
734 /* It isn't, so add it ourselves */
735 StringCchCat(ExpandedPath
, MAX_PATH
, L
"\\");
738 /* Add the database name */
739 StringCchCat(ExpandedPath
, MAX_PATH
, Name
);
741 /* Return a handle to the file */
742 Handle
= CreateFile(ExpandedPath
,
747 FILE_ATTRIBUTE_NORMAL
,
750 HeapFree(GetProcessHeap(), 0, ExpandedPath
);
755 NSP_GetServiceByNameHeapAllocW(_In_ PWSHANDLEINTERN data
,
756 _In_ DWORD dwControlFlags
,
757 _Out_ PWSHOSTINFOINTERN hostinfo
)
761 CHAR ServiceDBData
[BUFSIZ
* sizeof(WCHAR
)] = { 0 };
762 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
763 ProtocolStr
= 0, Comment
= 0, EndValid
;
764 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
770 PCHAR nameServiceA
= NULL
;
771 PCHAR nameProtoA
= NULL
;
772 INT res
= WSANO_RECOVERY
;
774 TRACE("NSP_GetServiceByNameHeapAllocW %p %lx %p\n", data
, dwControlFlags
, hostinfo
);
775 if (!data
->hostnameW
)
777 ERR("NSP_GetServiceByNameHeapAllocW service name not provided\n");
778 res
= WSANO_RECOVERY
;
782 hHeap
= GetProcessHeap();
783 nameA
= StrW2AHeapAlloc(hHeap
, data
->hostnameW
);
785 /* nameA has the form <service-name>/<protocol>
786 we split these now */
787 nameProtoA
= strchr(nameA
, '/');
788 if (nameProtoA
== NULL
)
790 ERR("NSP_GetServiceByNameHeapAllocW invalid service name %s\n", nameA
);
791 res
= WSANO_RECOVERY
;
796 i
= (DWORD
)(nameProtoA
- nameA
- 1);
797 nameServiceA
= (PCHAR
)HeapAlloc(hHeap
, 0, i
+ 1);
798 StringCbCopyA(nameServiceA
, i
+ 1, nameA
);
799 nameServiceA
[i
] = '\0';
801 ServicesFile
= OpenNetworkDatabase(L
"services");
802 if (ServicesFile
== INVALID_HANDLE_VALUE
)
804 ERR("NSP_GetServiceByNameHeapAllocW unable to open services file\n");
805 return WSANO_RECOVERY
;
808 /* Scan the services file ...
810 * We will be share the buffer on the lines. If the line does not fit in
811 * the buffer, then moving it to the beginning of the buffer and read
812 * the remnants of line from file.
816 if (!ReadFile(ServicesFile
,
818 sizeof( ServiceDBData
) - 1,
822 ERR("NSP_GetServiceByNameHeapAllocW can't read services file %lx\n", GetLastError());
823 CloseHandle(ServicesFile
);
824 return WSANO_RECOVERY
;
827 ThisLine
= NextLine
= ServiceDBData
;
828 EndValid
= ServiceDBData
+ ReadSize
;
829 ServiceDBData
[sizeof(ServiceDBData
) - 1] = '\0';
833 for (; *NextLine
!= '\r' && *NextLine
!= '\n'; NextLine
++)
835 if (NextLine
== EndValid
)
837 int LineLen
= NextLine
- ThisLine
;
839 if (ThisLine
== ServiceDBData
)
841 ERR("NSP_GetServiceByNameHeapAllocW line too long\n");
842 CloseHandle(ServicesFile
);
843 return WSANO_RECOVERY
;
846 memmove(ServiceDBData
, ThisLine
, LineLen
);
848 if (!ReadFile(ServicesFile
,
849 ServiceDBData
+ LineLen
,
850 sizeof( ServiceDBData
)-1 - LineLen
,
857 EndValid
= ServiceDBData
+ LineLen
+ ReadSize
;
858 NextLine
= ServiceDBData
+ LineLen
;
859 ThisLine
= ServiceDBData
;
861 if (!ReadSize
) break;
866 Comment
= strchr(ThisLine
, '#');
869 *Comment
= '\0'; /* Terminate at comment start */
871 if (DecodeServEntFromString(ThisLine
,
876 WS2_INTERNAL_MAX_ALIAS
) &&
877 (strlen(nameProtoA
) == 0 || strcmp(ProtocolStr
, nameProtoA
) == 0))
879 Found
= (strcmp(ServiceName
, nameServiceA
) == 0 || strcmp(PortNumberStr
, nameServiceA
) == 0);
881 while ((!Found
) && (*AliasPtr
!= NULL
))
883 Found
= (strcmp(*AliasPtr
, nameServiceA
) == 0);
893 /* This we'll do no matter what */
894 CloseHandle(ServicesFile
);
898 ERR("NSP_GetServiceByNameHeapAllocW service not found\n");
903 hostinfo
->servnameW
= StrA2WHeapAlloc(hHeap
, ServiceName
);
904 hostinfo
->servprotoW
= StrA2WHeapAlloc(hHeap
, ProtocolStr
);
905 hostinfo
->servaliasesA
= StrAryCpyHeapAllocA(hHeap
, (char**)&Aliases
);
906 hostinfo
->servport
= atoi(PortNumberStr
);
912 HeapFree(hHeap
, 0, nameA
);
915 HeapFree(hHeap
, 0, nameServiceA
);
921 NSP_LookupServiceNextW(_In_ PWSHANDLEINTERN data
,
922 _In_ DWORD dwControlFlags
,
923 _Inout_ LPWSAQUERYSETW lpRes
,
924 _Inout_ LPDWORD lpResLen
)
927 WSHOSTINFOINTERN hostinfo
;
929 HANDLE hHeap
= GetProcessHeap();
930 WCHAR
* ServiceInstanceNameW
= NULL
;
932 CHAR
* ServiceInstanceNameA
= NULL
;
933 CHAR
* ServiceProtocolNameA
= NULL
;
935 TRACE("NSP_LookupServiceNextW %p %lx %p %p\n", data
, dwControlFlags
, lpRes
, lpResLen
);
936 if (!data
|| (dwControlFlags
& (~(DWORD
)LUP_FLUSHPREVIOUS
)) != 0 || !lpRes
|| !lpResLen
|| *lpResLen
== 0)
938 RtlZeroMemory(&hostinfo
, sizeof(hostinfo
));
940 /* init and build result-buffer */
941 mswBufferInit(&buf
, (BYTE
*)lpRes
, *lpResLen
);
942 mswBufferIncUsed(&buf
, sizeof(*lpRes
));
944 /* QueryDataSet-Size without "blob-data"-size! */
945 lpRes
->dwSize
= sizeof(*lpRes
);
946 lpRes
->dwNameSpace
= NS_DNS
;
948 if ((data
->CallID
== NSP_CALLID_HOSTNAME
) ||
949 (data
->CallID
== NSP_CALLID_HOSTBYNAME
) ||
950 (data
->CallID
== NSP_CALLID_SERVICEBYNAME
))
952 /* FIXME remember what was returned and continue from there */
953 if (data
->CallIDCounter
>= 1)
955 ERR("NSP_LookupServiceNextW LUP_FLUSHPREVIOUS and more than one call not supported yet\n", data
, dwControlFlags
, lpRes
, lpResLen
);
956 result
= WSA_E_NO_MORE
;
962 ERR("NSP_LookupServiceNextW unsupported CallID %lx\n", data
->CallID
);
963 result
= WSAEOPNOTSUPP
;
966 data
->CallIDCounter
++;
968 if (data
->CallID
== NSP_CALLID_HOSTNAME
)
970 result
= NSP_GetHostNameHeapAllocW(&hostinfo
.hostnameW
);
972 if (result
!= ERROR_SUCCESS
)
977 else if (data
->CallID
== NSP_CALLID_HOSTBYNAME
)
979 result
= NSP_GetHostByNameHeapAllocW(data
,
982 if (result
!= ERROR_SUCCESS
)
987 //ASSERT(data->CallID == NSP_CALLID_SERVICEBYNAME);
988 result
= NSP_GetServiceByNameHeapAllocW(data
,
991 if (result
!= ERROR_SUCCESS
)
995 if (((LUP_RETURN_BLOB
& data
->dwControlFlags
) != 0) ||
996 ((LUP_RETURN_NAME
& data
->dwControlFlags
) != 0))
998 if (data
->CallID
== NSP_CALLID_HOSTNAME
|| data
->CallID
== NSP_CALLID_HOSTBYNAME
)
1000 ServiceInstanceNameW
= hostinfo
.hostnameW
;
1001 ServiceInstanceNameA
= StrW2AHeapAlloc(hHeap
, ServiceInstanceNameW
);
1002 if (!ServiceInstanceNameA
)
1004 ERR("NSP_LookupServiceNextW not enough memory\n");
1005 result
= WSA_NOT_ENOUGH_MEMORY
;
1009 if (data
->CallID
== NSP_CALLID_SERVICEBYNAME
)
1011 ServiceInstanceNameW
= hostinfo
.servnameW
;
1012 ServiceInstanceNameA
= StrW2AHeapAlloc(hHeap
, ServiceInstanceNameW
);
1013 if (!ServiceInstanceNameA
)
1015 ERR("NSP_LookupServiceNextW not enough memory\n");
1016 result
= WSA_NOT_ENOUGH_MEMORY
;
1019 ServiceProtocolNameA
= StrW2AHeapAlloc(hHeap
, hostinfo
.servprotoW
);
1020 if (!ServiceProtocolNameA
)
1022 ERR("NSP_LookupServiceNextW not enough memory\n");
1023 result
= WSA_NOT_ENOUGH_MEMORY
;
1029 if ((LUP_RETURN_ADDR
& data
->dwControlFlags
) != 0)
1031 if (!mswBufferAppendAddr_AddrInfoW(&buf
, lpRes
, hostinfo
.addr4
))
1033 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
1034 *lpResLen
= buf
.bytesUsed
;
1040 if ((LUP_RETURN_BLOB
& data
->dwControlFlags
) != 0)
1042 if (data
->CallID
== NSP_CALLID_HOSTBYNAME
)
1044 /* Write data for PBLOB (hostent) */
1045 if (!mswBufferAppendBlob_Hostent(&buf
,
1047 (LUP_RETURN_ALIASES
& data
->dwControlFlags
) != 0 ? hostinfo
.servaliasesA
: NULL
,
1048 ServiceInstanceNameA
,
1051 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
1052 *lpResLen
= buf
.bytesUsed
;
1057 else if (data
->CallID
== NSP_CALLID_SERVICEBYNAME
)
1059 /* Write data for PBLOB (servent) */
1060 if (!mswBufferAppendBlob_Servent(&buf
,
1062 ServiceInstanceNameA
,/* ServiceName */
1063 (LUP_RETURN_ALIASES
& data
->dwControlFlags
) != 0 ? hostinfo
.servaliasesA
: NULL
,
1064 ServiceProtocolNameA
,
1067 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
1068 *lpResLen
= buf
.bytesUsed
;
1075 ERR("NSP_LookupServiceNextW LUP_RETURN_BLOB is supported only for NSP_CALLID_HOSTBYNAME and NSP_CALLID_SERVICEBYNAME\n");
1081 if ((LUP_RETURN_NAME
& data
->dwControlFlags
) != 0)
1083 /* HostByName sets the ServiceInstanceName to a
1084 (UNICODE)copy of hostent.h_name */
1085 lpRes
->lpszServiceInstanceName
= (LPWSTR
)mswBufferEndPtr(&buf
);
1086 if (!mswBufferAppendStrW(&buf
, ServiceInstanceNameW
))
1088 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
1089 lpRes
->lpszServiceInstanceName
= NULL
;
1090 *lpResLen
= buf
.bytesUsed
;
1096 *lpResLen
= buf
.bytesUsed
;
1098 result
= ERROR_SUCCESS
;
1101 if (ServiceInstanceNameA
!= NULL
)
1102 HeapFree(hHeap
, 0, ServiceInstanceNameA
);
1104 if (ServiceProtocolNameA
!= NULL
)
1105 HeapFree(hHeap
, 0, ServiceProtocolNameA
);
1107 if (hostinfo
.hostnameW
!= NULL
)
1108 HeapFree(hHeap
, 0, hostinfo
.hostnameW
);
1110 if (hostinfo
.servnameW
!= NULL
)
1111 HeapFree(hHeap
, 0, hostinfo
.servnameW
);
1113 if (hostinfo
.servprotoW
!= NULL
)
1114 HeapFree(hHeap
, 0, hostinfo
.servprotoW
);
1116 TRACE("NSP_LookupServiceNextW returns %d needed bytes %ld\n", result
, buf
.bytesUsed
);
1120 /* Implementations - Exports */
1126 NSPStartup(_In_ LPGUID lpProviderId
,
1127 _Out_ LPNSP_ROUTINE lpRout
)
1131 TRACE("NSPStartup %p %p\n", lpProviderId
, lpRout
);
1132 if (!lpRout
|| (lpRout
->cbSize
!= sizeof(NSP_ROUTINE
)))
1134 ERR("NSPStartup invalid parameter\n");
1135 WSASetLastError(WSAEINVAL
);
1136 return ERROR_INVALID_PARAMETER
;
1141 /* set own Provider GUID - maybe we need
1142 here to set the original mswsock-GUID?! */
1147 - sets cbSize to 44! */
1148 lpRout
->dwMajorVersion
= 1;
1149 lpRout
->dwMinorVersion
= 1;
1150 lpRout
->cbSize
= sizeof(*lpRout
) - sizeof(lpRout
->NSPIoctl
);
1151 lpRout
->NSPCleanup
= &mwsNSPCleanUp
;
1152 lpRout
->NSPLookupServiceBegin
= &mwsNSPLookupServiceBegin
;
1153 lpRout
->NSPLookupServiceNext
= &mwsNSPLookupServiceNext
;
1154 lpRout
->NSPLookupServiceEnd
= &mwsNSPLookupServiceEnd
;
1155 lpRout
->NSPSetService
= &mwsNSPSetService
;
1156 lpRout
->NSPInstallServiceClass
= &mwsNSPInstallServiceClass
;
1157 lpRout
->NSPRemoveServiceClass
= &mwsNSPRemoveServiceClass
;
1158 lpRout
->NSPGetServiceClassInfo
= &mwsNSPGetServiceClassInfo
;
1159 lpRout
->NSPIoctl
= NULL
;// &mwsNSPIoCtl;