2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 SPI
4 * FILE: lib/mswsock/lib/init.c
5 * PURPOSE: DLL Initialization
8 /* INCLUDES ******************************************************************/
11 #define ALL_LUP_FLAGS (0x0BFFF)
13 /* DATA **********************************************************************/
18 GUID NbtProviderId
= {0};
19 GUID DNSProviderId
= {0};
22 NSP_ROUTINE g_NspVector
= {sizeof(NSP_ROUTINE
),
26 Dns_NSPLookupServiceBegin
,
27 Dns_NSPLookupServiceNext
,
28 Dns_NSPLookupServiceEnd
,
30 Dns_NSPInstallServiceClass
,
31 Dns_NSPRemoveServiceClass
,
32 Dns_NSPGetServiceClassInfo
};
34 /* FUNCTIONS *****************************************************************/
38 Dns_NSPStartup(IN LPGUID lpProviderId
,
39 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
44 /* Validate the size */
45 if (lpsnpRoutines
->cbSize
!= sizeof(NSP_ROUTINE
))
48 SetLastError(WSAEINVALIDPROCTABLE
);
52 /* Enter the prolog */
53 Prolog
= RNRPROV_SockEnterApi();
56 /* Increase our reference count */
57 InterlockedIncrement(&g_NspRefCount
);
59 /* Check if we don't have the hostname */
62 /* Query it from DNS */
63 DnsQueryConfig(DnsConfigHostName_W
,
64 DNS_CONFIG_FLAG_ALLOC
,
71 /* Check if we have a hostname now, but not a Fully-Qualified Domain */
72 if (g_pszHostName
&& !(g_pszHostFqdn
))
74 /* Get the domain from DNS */
75 DnsQueryConfig(DnsConfigFullHostName_W
,
76 DNS_CONFIG_FLAG_ALLOC
,
83 /* If we don't have both of them, then set error */
84 if (!(g_pszHostName
) || !(g_pszHostFqdn
)) ErrorCode
= SOCKET_ERROR
;
87 /* Check if the Prolog or DNS Local Queries failed */
88 if (!(Prolog
) || (ErrorCode
!= NO_ERROR
))
91 SetLastError(WSASYSNOTREADY
);
95 /* Copy the Routines */
96 RtlMoveMemory(lpsnpRoutines
, &g_NspVector
, sizeof(NSP_ROUTINE
));
98 /* Check if this is NBT or DNS */
99 if (!memcmp(lpProviderId
, &NbtProviderId
, sizeof(GUID
)))
101 /* Enable the NBT Mask */
102 MaskOfGuids
|= NBT_MASK
;
104 else if (!memcmp(lpProviderId
, &DNSProviderId
, sizeof(GUID
)))
106 /* Enable the DNS Mask */
107 MaskOfGuids
|= DNS_MASK
;
116 Nsp_GlobalCleanup(VOID
)
118 /* Cleanup the RnR Contexts */
119 RnrCtx_ListCleanup();
121 /* Free the hostnames, if we have them */
122 if (g_pszHostName
) DnsApiFree(g_pszHostName
);
123 if (g_pszHostFqdn
) DnsApiFree(g_pszHostFqdn
);
124 g_pszHostFqdn
= g_pszHostName
= NULL
;
129 NSPStartup(IN LPGUID lpProviderId
,
130 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
134 /* Initialize the DLL */
135 ErrorCode
= MSWSOCK_Initialize();
136 if (ErrorCode
!= NO_ERROR
)
139 SetLastError(WSANOTINITIALISED
);
143 /* Check if this is Winsock Mobile or DNS */
144 if (!memcmp(lpProviderId
, &gNLANamespaceGuid
, sizeof(GUID
)))
147 return WSM_NSPStartup(lpProviderId
, lpsnpRoutines
);
151 return Dns_NSPStartup(lpProviderId
, lpsnpRoutines
);
156 Dns_NSPCleanup(IN LPGUID lpProviderId
)
158 /* Decrement our reference count and do global cleanup if it's reached 0 */
159 if (!(InterlockedDecrement(&g_NspRefCount
))) Nsp_GlobalCleanup();
167 Dns_NSPSetService(IN LPGUID lpProviderId
,
168 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
,
169 IN LPWSAQUERYSETW lpqsRegInfo
,
170 IN WSAESETSERVICEOP essOperation
,
171 IN DWORD dwControlFlags
)
173 /* Unlike NLA, DNS Services cannot be dynmically modified */
174 SetLastError(ERROR_NOT_SUPPORTED
);
180 Dns_NSPInstallServiceClass(IN LPGUID lpProviderId
,
181 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
183 /* Unlike NLA, DNS Services cannot be dynmically modified */
184 SetLastError(WSAEOPNOTSUPP
);
190 Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId
,
191 IN LPGUID lpServiceCallId
)
193 /* Unlike NLA, DNS Services cannot be dynmically modified */
194 SetLastError(WSAEOPNOTSUPP
);
199 Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId
,
200 IN OUT LPDWORD lpdwBufSize
,
201 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
203 /* Unlike NLA, DNS Services cannot be dynmically modified */
204 SetLastError(WSAEOPNOTSUPP
);
210 Dns_NSPLookupServiceEnd(IN HANDLE hLookup
)
212 PRNR_CONTEXT RnrContext
;
214 /* Get this handle's context */
215 RnrContext
= RnrCtx_Get(hLookup
, 0, NULL
);
217 /* Mark it as completed */
218 RnrContext
->LookupFlags
|= DONE
;
220 /* Dereference it once for our _Get */
221 RnrCtx_Release(RnrContext
);
223 /* And once last to delete it */
224 RnrCtx_Release(RnrContext
);
232 rnr_IdForGuid(IN LPGUID Guid
)
235 if (memcmp(Guid
, &InetHostName
, sizeof(GUID
))) return 0x10000002;
236 if (memcmp(Guid
, &Ipv6Guid
, sizeof(GUID
))) return 0x10000023;
237 if (memcmp(Guid
, &HostnameGuid
, sizeof(GUID
))) return 0x1;
238 if (memcmp(Guid
, &AddressGuid
, sizeof(GUID
))) return 0x80000000;
239 if (memcmp(Guid
, &IANAGuid
, sizeof(GUID
))) return 0x2;
240 if IS_SVCID_DNS(Guid
) return 0x5000000;
241 if IS_SVCID_TCP(Guid
) return 0x1000000;
242 if IS_SVCID_UDP(Guid
) return 0x2000000;
248 FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer
,
251 /* Let DNSLIB do the grunt work */
252 return FlatBuf_Arg_Reserve((PVOID
)FlatBuffer
->BufferPos
,
253 &FlatBuffer
->BufferFreeSize
,
260 FlatBuf_WriteString(IN PFLATBUFF FlatBuffer
,
262 IN BOOLEAN IsUnicode
)
264 /* Let DNSLIB do the grunt work */
265 return FlatBuf_Arg_WriteString((PVOID
)FlatBuffer
->BufferPos
,
266 &FlatBuffer
->BufferFreeSize
,
273 FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer
,
278 /* Let DNSLIB do the grunt work */
279 return FlatBuf_Arg_CopyMemory((PVOID
)FlatBuffer
->BufferPos
,
280 &FlatBuffer
->BufferFreeSize
,
288 Dns_NSPLookupServiceBegin(LPGUID lpProviderId
,
289 LPWSAQUERYSETW lpqsRestrictions
,
290 LPWSASERVICECLASSINFOW lpServiceClassInfo
,
291 DWORD dwControlFlags
,
294 INT ErrorCode
= SOCKET_ERROR
;
295 PWCHAR ServiceName
= lpqsRestrictions
->lpszServiceInstanceName
;
296 LPGUID ServiceClassId
;
298 ULONG LookupFlags
= 0;
299 BOOL NameRequested
= FALSE
;
300 WCHAR StringBuffer
[48];
302 DWORD LocalProtocols
;
304 PSERVENT LookupServent
;
305 DWORD UdpPort
, TcpPort
;
306 PRNR_CONTEXT RnrContext
;
307 PSOCKADDR_IN ReverseSock
;
309 /* Check if the Size isn't weird */
310 if(lpqsRestrictions
->dwSize
< sizeof(WSAQUERYSETW
))
312 ErrorCode
= WSAEFAULT
;
317 ServiceClassId
= lpqsRestrictions
->lpServiceClassId
;
321 ErrorCode
= WSA_INVALID_PARAMETER
;
326 RnrId
= rnr_IdForGuid(ServiceClassId
);
328 /* Make sure that the control flags are valid */
329 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
330 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
331 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
333 /* Either non-recognized flags or invalid combos were passed */
334 ErrorCode
= WSA_INVALID_PARAMETER
;
338 /* Make sure that we have no context, and that LUP_CONTAINERS is not on */
339 if(((lpqsRestrictions
->lpszContext
) &&
340 (*lpqsRestrictions
->lpszContext
) &&
341 (wcscmp(lpqsRestrictions
->lpszContext
, L
"\\"))) ||
342 (dwControlFlags
& LUP_CONTAINERS
))
344 /* We don't support contexts or LUP_CONTAINERS */
345 ErrorCode
= WSANO_DATA
;
349 /* Is this a Reverse Lookup? */
350 if (RnrId
== 0x80000000)
352 /* Remember for later */
353 LookupFlags
= REVERSE
;
357 /* Is this a IANA Lookup? */
360 /* Mask out this flag since it's of no use now */
361 dwControlFlags
&= ~(LUP_RETURN_ADDR
);
363 /* This is a IANA lookup, remember for later */
367 /* Check if we need a name or not */
368 if ((RnrId
== 0x1) ||
369 (RnrId
== 0x10000002) ||
370 (RnrId
== 0x10000023) ||
371 (RnrId
== 0x10000022))
374 NameRequested
= TRUE
;
378 /* Final check to make sure if we need a name or not */
379 if (RnrId
& 0x3000000) NameRequested
= TRUE
;
381 /* No Service Name was specified */
382 if(!(ServiceName
) || !(*ServiceName
))
385 * A name was requested but no Service Name was given,
386 * so this is a local lookup
391 LookupFlags
|= LOCAL
;
394 else if((LookupFlags
& REVERSE
) &&
395 (lpqsRestrictions
->lpcsaBuffer
) &&
396 (lpqsRestrictions
->dwNumberOfCsAddrs
== 1))
398 /* Reverse lookup, make sure a CS Address is there */
399 ReverseSock
= (struct sockaddr_in
*)
400 lpqsRestrictions
->lpcsaBuffer
->RemoteAddr
.lpSockaddr
;
402 /* Convert address to Unicode */
403 MultiByteToWideChar(CP_ACP
,
405 inet_ntoa(ReverseSock
->sin_addr
),
410 /* Set it as the new name */
411 ServiceName
= StringBuffer
;
415 /* We can't do anything without a service name at this point */
416 ErrorCode
= WSA_INVALID_PARAMETER
;
420 else if(NameRequested
)
422 /* Check for meaningful DNS Names */
423 if (DnsNameCompare_W(ServiceName
, L
"localhost") ||
424 DnsNameCompare_W(ServiceName
, L
"loopback"))
426 /* This is the local and/or loopback DNS name */
427 LookupFlags
|= (LOCAL
| LOOPBACK
);
429 else if (DnsNameCompare_W(ServiceName
, g_pszHostName
) ||
430 DnsNameCompare_W(ServiceName
, g_pszHostFqdn
))
432 /* This is the local name of the computer */
433 LookupFlags
|= LOCAL
;
437 /* Check if any restrictions were made on the protocols */
438 if(lpqsRestrictions
->lpafpProtocols
)
440 /* Save our local copy to speed up the loop */
441 LocalProtocols
= lpqsRestrictions
->dwNumberOfProtocols
;
444 /* Loop the protocols */
445 for(i
= 0; LocalProtocols
--;)
447 /* Make sure it's a family that we recognize */
448 if ((lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET
) ||
449 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET6
) ||
450 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_UNSPEC
) ||
451 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_ATM
))
453 /* Find which one is used */
454 switch(lpqsRestrictions
->lpafpProtocols
[i
].iProtocol
)
457 ProtocolFlags
|= UDP
;
460 ProtocolFlags
|= TCP
;
463 ProtocolFlags
|= ATM
;
470 /* Make sure we have at least a valid protocol */
474 ErrorCode
= WSANO_DATA
;
480 /* No restrictions, assume TCP/UDP */
481 ProtocolFlags
= (TCP
| UDP
);
484 /* Create the Servent from the Service String */
485 UdpPort
= TcpPort
= -1;
486 ProtocolFlags
|= GetServerAndProtocolsFromString(lpqsRestrictions
->lpszQueryString
,
490 /* Extract the port numbers */
493 /* Are we using UDP? */
494 if(ProtocolFlags
& UDP
)
496 /* Get the UDP Port, disable the TCP Port */
497 UdpPort
= ntohs(LookupServent
->s_port
);
500 else if(ProtocolFlags
& TCP
)
502 /* Get the TCP Port, disable the UDP Port */
503 TcpPort
= ntohs(LookupServent
->s_port
);
509 /* No servent, so use the Service ID to check */
510 if(ProtocolFlags
& UDP
)
512 /* Get the Port from the Service ID */
513 UdpPort
= FetchPortFromClassInfo(UDP
,
523 /* No servent, so use the Service ID to check */
524 if(ProtocolFlags
& TCP
)
526 /* Get the Port from the Service ID */
527 UdpPort
= FetchPortFromClassInfo(TCP
,
538 /* Check if we still don't have a valid port by now */
539 if((TcpPort
== -1) && (UdpPort
== -1))
541 /* Check if this is TCP */
542 if ((ProtocolFlags
& TCP
) || !(ProtocolFlags
& UDP
))
544 /* Set the UDP Port to 0 */
549 /* Set the TCP Port to 0 */
554 /* Allocate a Context for this Query */
555 RnrContext
= RnrCtx_Create(NULL
, ServiceName
);
556 RnrContext
->lpServiceClassId
= *ServiceClassId
;
557 RnrContext
->RnrId
= RnrId
;
558 RnrContext
->dwControlFlags
= dwControlFlags
;
559 RnrContext
->TcpPort
= TcpPort
;
560 RnrContext
->UdpPort
= UdpPort
;
561 RnrContext
->LookupFlags
= LookupFlags
;
562 RnrContext
->lpProviderId
= *lpProviderId
;
563 RnrContext
->dwNameSpace
= lpqsRestrictions
->dwNameSpace
;
564 RnrCtx_Release(RnrContext
);
566 /* Return the context as a handle */
567 *lphLookup
= (HANDLE
)RnrContext
;
569 /* Check if this was a TCP, UDP or DNS Query */
570 if(RnrId
& 0x3000000)
572 /* Get the RR Type from the Service ID */
573 RnrContext
->RrType
= RR_FROM_SVCID(ServiceClassId
);
577 ErrorCode
= ERROR_SUCCESS
;
580 /* Check if we got here through a failure path */
581 if (ErrorCode
!= ERROR_SUCCESS
)
583 /* Set the last error and fail */
584 SetLastError(ErrorCode
);
589 return ERROR_SUCCESS
;
594 BuildCsAddr(IN LPWSAQUERYSETW QuerySet
,
595 IN PFLATBUFF FlatBuffer
,
599 IN BOOLEAN ReverseLookup
)
606 Dns_NSPLookupServiceNext(IN HANDLE hLookup
,
607 IN DWORD dwControlFlags
,
608 IN OUT LPDWORD lpdwBufferLength
,
609 OUT LPWSAQUERYSETW lpqsResults
)
612 WSAQUERYSETW LocalResults
;
614 PRNR_CONTEXT RnrContext
= NULL
;
617 PDNS_BLOB Blob
= NULL
;
619 PSERVENT ServEntry
= NULL
;
621 BOOLEAN IsUnicode
= TRUE
;
625 PVOID BlobData
= NULL
;
629 /* Make sure that the control flags are valid */
630 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
631 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
632 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
634 /* Either non-recognized flags or invalid combos were passed */
635 ErrorCode
= WSA_INVALID_PARAMETER
;
639 /* Get the Context */
640 RnrContext
= RnrCtx_Get(hLookup
, dwControlFlags
, &Instance
);
643 /* This lookup handle must be invalid */
644 SetLastError(WSA_INVALID_HANDLE
);
648 /* Assume success for now */
649 SetLastError(NO_ERROR
);
651 /* Validate the query set size */
652 if (*lpdwBufferLength
< sizeof(WSAQUERYSETW
))
654 /* Windows doesn't fail, but sets up a local QS for you... */
655 lpqsResults
= &LocalResults
;
656 ErrorCode
= WSAEFAULT
;
659 /* Zero out the buffer and fill out basic data */
660 RtlZeroMemory(lpqsResults
, sizeof(WSAQUERYSETW
));
661 lpqsResults
->dwNameSpace
= NS_DNS
;
662 lpqsResults
->dwSize
= sizeof(WSAQUERYSETW
);
664 /* Initialize the Buffer */
665 FlatBuf_Init(&FlatBuffer
,
667 (ULONG
)(*lpdwBufferLength
- sizeof(WSAQUERYSETW
)));
669 /* Check if this is an IANA Lookup */
670 if(RnrContext
->LookupFlags
& IANA
)
673 GetServerAndProtocolsFromString(RnrContext
->ServiceName
,
674 (LPGUID
)&HostnameGuid
,
678 PortNumber
= ntohs(ServEntry
->s_port
);
680 /* Use this as the name */
681 Name
= ServEntry
->s_name
;
684 /* Override some parts of the Context and check for TCP/UDP */
685 if(!_stricmp("tcp", ServEntry
->s_proto
))
687 /* Set the TCP Guid */
688 SET_TCP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
689 RnrContext
->TcpPort
= PortNumber
;
690 RnrContext
->UdpPort
= -1;
694 /* Set the UDP Guid */
695 SET_UDP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
696 RnrContext
->UdpPort
= PortNumber
;
697 RnrContext
->TcpPort
= -1;
702 /* Check if the caller requested for RES_SERVICE */
703 if(RnrContext
->dwControlFlags
& LUP_RES_SERVICE
)
705 /* Make sure that this is the first instance */
709 ErrorCode
= WSA_E_NO_MORE
;
714 /* Create the blob */
716 Blob
= SaBlob_CreateFromIp4(RnrContext
->ServiceName
,
723 ErrorCode
= WSAEFAULT
;
727 else if(!(Blob
= RnrContext
->CachedSaBlob
))
729 /* An actual Host Lookup, but we don't have a cached HostEntry yet */
730 if (!memcmp(&RnrContext
->lpServiceClassId
,
732 sizeof(GUID
)) && !(RnrContext
->ServiceName
))
734 /* Do a Regular DNS Lookup */
735 Blob
= Rnr_DoHostnameLookup(RnrContext
);
737 else if (RnrContext
->LookupFlags
& REVERSE
)
739 /* Do a Reverse DNS Lookup */
740 Blob
= Rnr_GetHostByAddr(RnrContext
);
744 /* Do a Hostname Lookup */
745 Blob
= Rnr_DoDnsLookup(RnrContext
);
748 /* Check if we got a blob, and cache it */
749 if (Blob
) RnrContext
->CachedSaBlob
= Blob
;
752 /* We should have a blob by now */
756 if (ErrorCode
== NO_ERROR
)
758 /* Supposedly no error, so find it out */
759 ErrorCode
= GetLastError();
760 if (ErrorCode
== NO_ERROR
) ErrorCode
= WSASERVICE_NOT_FOUND
;
768 /* Check if this is the first instance or not */
769 if(!RnrContext
->Instance
)
771 /* It is, get the name from the blob */
776 /* Only accept this scenario if the caller wanted Aliases */
777 if((RnrContext
->dwControlFlags
& LUP_RETURN_ALIASES
) &&
778 (Blob
->AliasCount
> RnrContext
->Instance
))
780 /* Get the name from the Alias */
781 Name
= Blob
->Aliases
[RnrContext
->Instance
];
783 /* Let the caller know that this is an Alias */
784 /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */
789 ErrorCode
= WSA_E_NO_MORE
;
794 /* Lookups are complete... time to return the right stuff! */
795 lpqsResults
->dwNameSpace
= NS_DNS
;
797 /* Caller wants the Type back */
798 if(RnrContext
->dwControlFlags
& LUP_RETURN_TYPE
)
800 /* Copy into the flat buffer and point to it */
801 lpqsResults
->lpServiceClassId
= FlatBuf_CopyMemory(&FlatBuffer
,
802 &RnrContext
->lpServiceClassId
,
807 /* Caller wants the Addreses Back */
808 if((RnrContext
->dwControlFlags
& LUP_RETURN_ADDR
) && (Blob
))
810 /* Build the CS Addr for the caller */
811 ErrorCode
= BuildCsAddr(lpqsResults
,
816 (RnrContext
->LookupFlags
& REVERSE
) == 1);
819 /* Caller wants a Blob */
820 if(RnrContext
->dwControlFlags
& LUP_RETURN_BLOB
)
822 /* Save the current size and position */
823 FreeSize
= FlatBuffer
.BufferFreeSize
;
824 Position
= FlatBuffer
.BufferPos
;
826 /* Allocate some space for the Public Blob */
827 lpqsResults
->lpBlob
= FlatBuf_ReserveAlignDword(&FlatBuffer
,
830 /* Check for a Cached Blob */
831 if((RnrContext
->RrType
) && (RnrContext
->CachedBlob
.pBlobData
))
833 /* We have a Cached Blob, use it */
834 BlobSize
= RnrContext
->CachedBlob
.cbSize
;
835 BlobData
= FlatBuf_ReserveAlignDword(&FlatBuffer
, BlobSize
);
837 /* Copy into the blob */
838 RtlCopyMemory(RnrContext
->CachedBlob
.pBlobData
,
844 /* Create an ANSI Host Entry */
845 BlobData
= SaBlob_CreateHostent(&FlatBuffer
.BufferPos
,
846 &FlatBuffer
.BufferFreeSize
,
853 else if ((RnrContext
->LookupFlags
& IANA
) && (ServEntry
))
856 BlobData
= CopyServEntry(ServEntry
,
857 &FlatBuffer
.BufferPos
,
858 &FlatBuffer
.BufferFreeSize
,
862 /* Manually update the buffer (no SaBlob function for servents) */
863 FlatBuffer
.BufferPos
+= BlobSize
;
864 FlatBuffer
.BufferFreeSize
-= BlobSize
;
868 /* We have nothing to return! */
870 lpqsResults
->lpBlob
= NULL
;
871 FlatBuffer
.BufferPos
= Position
;
872 FlatBuffer
.BufferFreeSize
= FreeSize
;
875 /* Make sure we have a blob by here */
879 lpqsResults
->lpBlob
->pBlobData
= BlobData
;
880 lpqsResults
->lpBlob
->cbSize
= BlobSize
;
884 /* Set the error code */
885 ErrorCode
= WSAEFAULT
;
889 /* Caller wants a name, and we have one */
890 if((RnrContext
->dwControlFlags
& LUP_RETURN_NAME
) && (Name
))
892 /* Check if we have an ANSI name */
897 Dns_StringCopy(&UnicodeName
,
906 /* Keep the name as is */
907 UnicodeName
= (LPWSTR
)Name
;
910 /* Write it to the buffer */
911 Name
= FlatBuf_WriteString(&FlatBuffer
, UnicodeName
, TRUE
);
913 /* Return it to the caller */
914 lpqsResults
->lpszServiceInstanceName
= Name
;
918 /* Check which path got us here */
919 if (ErrorCode
!= NO_ERROR
)
922 SetLastError(ErrorCode
);
924 /* Check if was a memory error */
925 if (ErrorCode
== WSAEFAULT
)
927 /* Update buffer length */
928 *lpdwBufferLength
-= (DWORD
)FlatBuffer
.BufferFreeSize
;
930 /* Decrease an instance */
931 RnrCtx_DecInstance(RnrContext
);
934 /* Set the normalized error code */
935 ErrorCode
= SOCKET_ERROR
;
938 /* Release the RnR Context */
939 RnrCtx_Release(RnrContext
);
941 /* Return error code */
946 * COPYRIGHT: See COPYING in the top level directory
947 * PROJECT: ReactOS Winsock 2 SPI
948 * FILE: lib/mswsock/lib/init.c
949 * PURPOSE: DLL Initialization
952 /* INCLUDES ******************************************************************/
955 #define ALL_LUP_FLAGS (0x0BFFF)
957 /* DATA **********************************************************************/
959 LPWSTR g_pszHostName
;
960 LPWSTR g_pszHostFqdn
;
962 GUID NbtProviderId
= {0};
963 GUID DNSProviderId
= {0};
966 NSP_ROUTINE g_NspVector
= {sizeof(NSP_ROUTINE
),
970 Dns_NSPLookupServiceBegin
,
971 Dns_NSPLookupServiceNext
,
972 Dns_NSPLookupServiceEnd
,
974 Dns_NSPInstallServiceClass
,
975 Dns_NSPRemoveServiceClass
,
976 Dns_NSPGetServiceClassInfo
};
978 /* FUNCTIONS *****************************************************************/
982 Dns_NSPStartup(IN LPGUID lpProviderId
,
983 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
988 /* Validate the size */
989 if (lpsnpRoutines
->cbSize
!= sizeof(NSP_ROUTINE
))
992 SetLastError(WSAEINVALIDPROCTABLE
);
996 /* Enter the prolog */
997 Prolog
= RNRPROV_SockEnterApi();
1000 /* Increase our reference count */
1001 InterlockedIncrement(&g_NspRefCount
);
1003 /* Check if we don't have the hostname */
1006 /* Query it from DNS */
1007 DnsQueryConfig(DnsConfigHostName_W
,
1008 DNS_CONFIG_FLAG_ALLOC
,
1015 /* Check if we have a hostname now, but not a Fully-Qualified Domain */
1016 if (g_pszHostName
&& !(g_pszHostFqdn
))
1018 /* Get the domain from DNS */
1019 DnsQueryConfig(DnsConfigFullHostName_W
,
1020 DNS_CONFIG_FLAG_ALLOC
,
1027 /* If we don't have both of them, then set error */
1028 if (!(g_pszHostName
) || !(g_pszHostFqdn
)) ErrorCode
= SOCKET_ERROR
;
1031 /* Check if the Prolog or DNS Local Queries failed */
1032 if (!(Prolog
) || (ErrorCode
!= NO_ERROR
))
1035 SetLastError(WSASYSNOTREADY
);
1036 return SOCKET_ERROR
;
1039 /* Copy the Routines */
1040 RtlMoveMemory(lpsnpRoutines
, &g_NspVector
, sizeof(NSP_ROUTINE
));
1042 /* Check if this is NBT or DNS */
1043 if (!memcmp(lpProviderId
, &NbtProviderId
, sizeof(GUID
)))
1045 /* Enable the NBT Mask */
1046 MaskOfGuids
|= NBT_MASK
;
1048 else if (!memcmp(lpProviderId
, &DNSProviderId
, sizeof(GUID
)))
1050 /* Enable the DNS Mask */
1051 MaskOfGuids
|= DNS_MASK
;
1054 /* Return success */
1060 Nsp_GlobalCleanup(VOID
)
1062 /* Cleanup the RnR Contexts */
1063 RnrCtx_ListCleanup();
1065 /* Free the hostnames, if we have them */
1066 if (g_pszHostName
) DnsApiFree(g_pszHostName
);
1067 if (g_pszHostFqdn
) DnsApiFree(g_pszHostFqdn
);
1068 g_pszHostFqdn
= g_pszHostName
= NULL
;
1073 NSPStartup(IN LPGUID lpProviderId
,
1074 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
1078 /* Initialize the DLL */
1079 ErrorCode
= MSWSOCK_Initialize();
1080 if (ErrorCode
!= NO_ERROR
)
1083 SetLastError(WSANOTINITIALISED
);
1084 return SOCKET_ERROR
;
1087 /* Check if this is Winsock Mobile or DNS */
1088 if (!memcmp(lpProviderId
, &gNLANamespaceGuid
, sizeof(GUID
)))
1090 /* Initialize WSM */
1091 return WSM_NSPStartup(lpProviderId
, lpsnpRoutines
);
1094 /* Initialize DNS */
1095 return Dns_NSPStartup(lpProviderId
, lpsnpRoutines
);
1100 Dns_NSPCleanup(IN LPGUID lpProviderId
)
1102 /* Decrement our reference count and do global cleanup if it's reached 0 */
1103 if (!(InterlockedDecrement(&g_NspRefCount
))) Nsp_GlobalCleanup();
1105 /* Return success */
1111 Dns_NSPSetService(IN LPGUID lpProviderId
,
1112 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
,
1113 IN LPWSAQUERYSETW lpqsRegInfo
,
1114 IN WSAESETSERVICEOP essOperation
,
1115 IN DWORD dwControlFlags
)
1117 /* Unlike NLA, DNS Services cannot be dynmically modified */
1118 SetLastError(ERROR_NOT_SUPPORTED
);
1119 return SOCKET_ERROR
;
1124 Dns_NSPInstallServiceClass(IN LPGUID lpProviderId
,
1125 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
1127 /* Unlike NLA, DNS Services cannot be dynmically modified */
1128 SetLastError(WSAEOPNOTSUPP
);
1129 return SOCKET_ERROR
;
1134 Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId
,
1135 IN LPGUID lpServiceCallId
)
1137 /* Unlike NLA, DNS Services cannot be dynmically modified */
1138 SetLastError(WSAEOPNOTSUPP
);
1139 return SOCKET_ERROR
;
1143 Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId
,
1144 IN OUT LPDWORD lpdwBufSize
,
1145 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
1147 /* Unlike NLA, DNS Services cannot be dynmically modified */
1148 SetLastError(WSAEOPNOTSUPP
);
1149 return SOCKET_ERROR
;
1154 Dns_NSPLookupServiceEnd(IN HANDLE hLookup
)
1156 PRNR_CONTEXT RnrContext
;
1158 /* Get this handle's context */
1159 RnrContext
= RnrCtx_Get(hLookup
, 0, NULL
);
1161 /* Mark it as completed */
1162 RnrContext
->LookupFlags
|= DONE
;
1164 /* Dereference it once for our _Get */
1165 RnrCtx_Release(RnrContext
);
1167 /* And once last to delete it */
1168 RnrCtx_Release(RnrContext
);
1176 rnr_IdForGuid(IN LPGUID Guid
)
1179 if (memcmp(Guid
, &InetHostName
, sizeof(GUID
))) return 0x10000002;
1180 if (memcmp(Guid
, &Ipv6Guid
, sizeof(GUID
))) return 0x10000023;
1181 if (memcmp(Guid
, &HostnameGuid
, sizeof(GUID
))) return 0x1;
1182 if (memcmp(Guid
, &AddressGuid
, sizeof(GUID
))) return 0x80000000;
1183 if (memcmp(Guid
, &IANAGuid
, sizeof(GUID
))) return 0x2;
1184 if IS_SVCID_DNS(Guid
) return 0x5000000;
1185 if IS_SVCID_TCP(Guid
) return 0x1000000;
1186 if IS_SVCID_UDP(Guid
) return 0x2000000;
1192 FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer
,
1195 /* Let DNSLIB do the grunt work */
1196 return FlatBuf_Arg_Reserve((PVOID
)FlatBuffer
->BufferPos
,
1197 &FlatBuffer
->BufferFreeSize
,
1204 FlatBuf_WriteString(IN PFLATBUFF FlatBuffer
,
1206 IN BOOLEAN IsUnicode
)
1208 /* Let DNSLIB do the grunt work */
1209 return FlatBuf_Arg_WriteString((PVOID
)FlatBuffer
->BufferPos
,
1210 &FlatBuffer
->BufferFreeSize
,
1217 FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer
,
1222 /* Let DNSLIB do the grunt work */
1223 return FlatBuf_Arg_CopyMemory((PVOID
)FlatBuffer
->BufferPos
,
1224 &FlatBuffer
->BufferFreeSize
,
1232 Dns_NSPLookupServiceBegin(LPGUID lpProviderId
,
1233 LPWSAQUERYSETW lpqsRestrictions
,
1234 LPWSASERVICECLASSINFOW lpServiceClassInfo
,
1235 DWORD dwControlFlags
,
1238 INT ErrorCode
= SOCKET_ERROR
;
1239 PWCHAR ServiceName
= lpqsRestrictions
->lpszServiceInstanceName
;
1240 LPGUID ServiceClassId
;
1242 ULONG LookupFlags
= 0;
1243 BOOL NameRequested
= FALSE
;
1244 WCHAR StringBuffer
[48];
1246 DWORD LocalProtocols
;
1247 ULONG ProtocolFlags
;
1248 PSERVENT LookupServent
;
1249 DWORD UdpPort
, TcpPort
;
1250 PRNR_CONTEXT RnrContext
;
1251 PSOCKADDR_IN ReverseSock
;
1253 /* Check if the Size isn't weird */
1254 if(lpqsRestrictions
->dwSize
< sizeof(WSAQUERYSETW
))
1256 ErrorCode
= WSAEFAULT
;
1261 ServiceClassId
= lpqsRestrictions
->lpServiceClassId
;
1265 ErrorCode
= WSA_INVALID_PARAMETER
;
1269 /* Get the RNR ID */
1270 RnrId
= rnr_IdForGuid(ServiceClassId
);
1272 /* Make sure that the control flags are valid */
1273 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
1274 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
1275 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
1277 /* Either non-recognized flags or invalid combos were passed */
1278 ErrorCode
= WSA_INVALID_PARAMETER
;
1282 /* Make sure that we have no context, and that LUP_CONTAINERS is not on */
1283 if(((lpqsRestrictions
->lpszContext
) &&
1284 (*lpqsRestrictions
->lpszContext
) &&
1285 (wcscmp(lpqsRestrictions
->lpszContext
, L
"\\"))) ||
1286 (dwControlFlags
& LUP_CONTAINERS
))
1288 /* We don't support contexts or LUP_CONTAINERS */
1289 ErrorCode
= WSANO_DATA
;
1293 /* Is this a Reverse Lookup? */
1294 if (RnrId
== 0x80000000)
1296 /* Remember for later */
1297 LookupFlags
= REVERSE
;
1301 /* Is this a IANA Lookup? */
1304 /* Mask out this flag since it's of no use now */
1305 dwControlFlags
&= ~(LUP_RETURN_ADDR
);
1307 /* This is a IANA lookup, remember for later */
1308 LookupFlags
|= IANA
;
1311 /* Check if we need a name or not */
1312 if ((RnrId
== 0x1) ||
1313 (RnrId
== 0x10000002) ||
1314 (RnrId
== 0x10000023) ||
1315 (RnrId
== 0x10000022))
1318 NameRequested
= TRUE
;
1322 /* Final check to make sure if we need a name or not */
1323 if (RnrId
& 0x3000000) NameRequested
= TRUE
;
1325 /* No Service Name was specified */
1326 if(!(ServiceName
) || !(*ServiceName
))
1329 * A name was requested but no Service Name was given,
1330 * so this is a local lookup
1334 /* A local Lookup */
1335 LookupFlags
|= LOCAL
;
1338 else if((LookupFlags
& REVERSE
) &&
1339 (lpqsRestrictions
->lpcsaBuffer
) &&
1340 (lpqsRestrictions
->dwNumberOfCsAddrs
== 1))
1342 /* Reverse lookup, make sure a CS Address is there */
1343 ReverseSock
= (struct sockaddr_in
*)
1344 lpqsRestrictions
->lpcsaBuffer
->RemoteAddr
.lpSockaddr
;
1346 /* Convert address to Unicode */
1347 MultiByteToWideChar(CP_ACP
,
1349 inet_ntoa(ReverseSock
->sin_addr
),
1354 /* Set it as the new name */
1355 ServiceName
= StringBuffer
;
1359 /* We can't do anything without a service name at this point */
1360 ErrorCode
= WSA_INVALID_PARAMETER
;
1364 else if(NameRequested
)
1366 /* Check for meaningful DNS Names */
1367 if (DnsNameCompare_W(ServiceName
, L
"localhost") ||
1368 DnsNameCompare_W(ServiceName
, L
"loopback"))
1370 /* This is the local and/or loopback DNS name */
1371 LookupFlags
|= (LOCAL
| LOOPBACK
);
1373 else if (DnsNameCompare_W(ServiceName
, g_pszHostName
) ||
1374 DnsNameCompare_W(ServiceName
, g_pszHostFqdn
))
1376 /* This is the local name of the computer */
1377 LookupFlags
|= LOCAL
;
1381 /* Check if any restrictions were made on the protocols */
1382 if(lpqsRestrictions
->lpafpProtocols
)
1384 /* Save our local copy to speed up the loop */
1385 LocalProtocols
= lpqsRestrictions
->dwNumberOfProtocols
;
1388 /* Loop the protocols */
1389 for(i
= 0; LocalProtocols
--;)
1391 /* Make sure it's a family that we recognize */
1392 if ((lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET
) ||
1393 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET6
) ||
1394 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_UNSPEC
) ||
1395 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_ATM
))
1397 /* Find which one is used */
1398 switch(lpqsRestrictions
->lpafpProtocols
[i
].iProtocol
)
1401 ProtocolFlags
|= UDP
;
1404 ProtocolFlags
|= TCP
;
1407 ProtocolFlags
|= ATM
;
1414 /* Make sure we have at least a valid protocol */
1418 ErrorCode
= WSANO_DATA
;
1424 /* No restrictions, assume TCP/UDP */
1425 ProtocolFlags
= (TCP
| UDP
);
1428 /* Create the Servent from the Service String */
1429 UdpPort
= TcpPort
= -1;
1430 ProtocolFlags
|= GetServerAndProtocolsFromString(lpqsRestrictions
->lpszQueryString
,
1434 /* Extract the port numbers */
1437 /* Are we using UDP? */
1438 if(ProtocolFlags
& UDP
)
1440 /* Get the UDP Port, disable the TCP Port */
1441 UdpPort
= ntohs(LookupServent
->s_port
);
1444 else if(ProtocolFlags
& TCP
)
1446 /* Get the TCP Port, disable the UDP Port */
1447 TcpPort
= ntohs(LookupServent
->s_port
);
1453 /* No servent, so use the Service ID to check */
1454 if(ProtocolFlags
& UDP
)
1456 /* Get the Port from the Service ID */
1457 UdpPort
= FetchPortFromClassInfo(UDP
,
1459 lpServiceClassInfo
);
1467 /* No servent, so use the Service ID to check */
1468 if(ProtocolFlags
& TCP
)
1470 /* Get the Port from the Service ID */
1471 UdpPort
= FetchPortFromClassInfo(TCP
,
1473 lpServiceClassInfo
);
1482 /* Check if we still don't have a valid port by now */
1483 if((TcpPort
== -1) && (UdpPort
== -1))
1485 /* Check if this is TCP */
1486 if ((ProtocolFlags
& TCP
) || !(ProtocolFlags
& UDP
))
1488 /* Set the UDP Port to 0 */
1493 /* Set the TCP Port to 0 */
1498 /* Allocate a Context for this Query */
1499 RnrContext
= RnrCtx_Create(NULL
, ServiceName
);
1500 RnrContext
->lpServiceClassId
= *ServiceClassId
;
1501 RnrContext
->RnrId
= RnrId
;
1502 RnrContext
->dwControlFlags
= dwControlFlags
;
1503 RnrContext
->TcpPort
= TcpPort
;
1504 RnrContext
->UdpPort
= UdpPort
;
1505 RnrContext
->LookupFlags
= LookupFlags
;
1506 RnrContext
->lpProviderId
= *lpProviderId
;
1507 RnrContext
->dwNameSpace
= lpqsRestrictions
->dwNameSpace
;
1508 RnrCtx_Release(RnrContext
);
1510 /* Return the context as a handle */
1511 *lphLookup
= (HANDLE
)RnrContext
;
1513 /* Check if this was a TCP, UDP or DNS Query */
1514 if(RnrId
& 0x3000000)
1516 /* Get the RR Type from the Service ID */
1517 RnrContext
->RrType
= RR_FROM_SVCID(ServiceClassId
);
1520 /* Return Success */
1521 ErrorCode
= ERROR_SUCCESS
;
1524 /* Check if we got here through a failure path */
1525 if (ErrorCode
!= ERROR_SUCCESS
)
1527 /* Set the last error and fail */
1528 SetLastError(ErrorCode
);
1529 return SOCKET_ERROR
;
1532 /* Return success */
1533 return ERROR_SUCCESS
;
1538 BuildCsAddr(IN LPWSAQUERYSETW QuerySet
,
1539 IN PFLATBUFF FlatBuffer
,
1543 IN BOOLEAN ReverseLookup
)
1550 Dns_NSPLookupServiceNext(IN HANDLE hLookup
,
1551 IN DWORD dwControlFlags
,
1552 IN OUT LPDWORD lpdwBufferLength
,
1553 OUT LPWSAQUERYSETW lpqsResults
)
1556 WSAQUERYSETW LocalResults
;
1558 PRNR_CONTEXT RnrContext
= NULL
;
1559 FLATBUFF FlatBuffer
;
1561 PDNS_BLOB Blob
= NULL
;
1563 PSERVENT ServEntry
= NULL
;
1564 PDNS_ARRAY DnsArray
;
1565 BOOLEAN IsUnicode
= TRUE
;
1569 PVOID BlobData
= NULL
;
1573 /* Make sure that the control flags are valid */
1574 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
1575 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
1576 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
1578 /* Either non-recognized flags or invalid combos were passed */
1579 ErrorCode
= WSA_INVALID_PARAMETER
;
1583 /* Get the Context */
1584 RnrContext
= RnrCtx_Get(hLookup
, dwControlFlags
, &Instance
);
1587 /* This lookup handle must be invalid */
1588 SetLastError(WSA_INVALID_HANDLE
);
1589 return SOCKET_ERROR
;
1592 /* Assume success for now */
1593 SetLastError(NO_ERROR
);
1595 /* Validate the query set size */
1596 if (*lpdwBufferLength
< sizeof(WSAQUERYSETW
))
1598 /* Windows doesn't fail, but sets up a local QS for you... */
1599 lpqsResults
= &LocalResults
;
1600 ErrorCode
= WSAEFAULT
;
1603 /* Zero out the buffer and fill out basic data */
1604 RtlZeroMemory(lpqsResults
, sizeof(WSAQUERYSETW
));
1605 lpqsResults
->dwNameSpace
= NS_DNS
;
1606 lpqsResults
->dwSize
= sizeof(WSAQUERYSETW
);
1608 /* Initialize the Buffer */
1609 FlatBuf_Init(&FlatBuffer
,
1611 (ULONG
)(*lpdwBufferLength
- sizeof(WSAQUERYSETW
)));
1613 /* Check if this is an IANA Lookup */
1614 if(RnrContext
->LookupFlags
& IANA
)
1616 /* Service Lookup */
1617 GetServerAndProtocolsFromString(RnrContext
->ServiceName
,
1618 (LPGUID
)&HostnameGuid
,
1622 PortNumber
= ntohs(ServEntry
->s_port
);
1624 /* Use this as the name */
1625 Name
= ServEntry
->s_name
;
1628 /* Override some parts of the Context and check for TCP/UDP */
1629 if(!_stricmp("tcp", ServEntry
->s_proto
))
1631 /* Set the TCP Guid */
1632 SET_TCP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
1633 RnrContext
->TcpPort
= PortNumber
;
1634 RnrContext
->UdpPort
= -1;
1638 /* Set the UDP Guid */
1639 SET_UDP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
1640 RnrContext
->UdpPort
= PortNumber
;
1641 RnrContext
->TcpPort
= -1;
1646 /* Check if the caller requested for RES_SERVICE */
1647 if(RnrContext
->dwControlFlags
& LUP_RES_SERVICE
)
1649 /* Make sure that this is the first instance */
1653 ErrorCode
= WSA_E_NO_MORE
;
1658 /* Create the blob */
1660 Blob
= SaBlob_CreateFromIp4(RnrContext
->ServiceName
,
1667 ErrorCode
= WSAEFAULT
;
1671 else if(!(Blob
= RnrContext
->CachedSaBlob
))
1673 /* An actual Host Lookup, but we don't have a cached HostEntry yet */
1674 if (!memcmp(&RnrContext
->lpServiceClassId
,
1676 sizeof(GUID
)) && !(RnrContext
->ServiceName
))
1678 /* Do a Regular DNS Lookup */
1679 Blob
= Rnr_DoHostnameLookup(RnrContext
);
1681 else if (RnrContext
->LookupFlags
& REVERSE
)
1683 /* Do a Reverse DNS Lookup */
1684 Blob
= Rnr_GetHostByAddr(RnrContext
);
1688 /* Do a Hostname Lookup */
1689 Blob
= Rnr_DoDnsLookup(RnrContext
);
1692 /* Check if we got a blob, and cache it */
1693 if (Blob
) RnrContext
->CachedSaBlob
= Blob
;
1696 /* We should have a blob by now */
1700 if (ErrorCode
== NO_ERROR
)
1702 /* Supposedly no error, so find it out */
1703 ErrorCode
= GetLastError();
1704 if (ErrorCode
== NO_ERROR
) ErrorCode
= WSASERVICE_NOT_FOUND
;
1712 /* Check if this is the first instance or not */
1713 if(!RnrContext
->Instance
)
1715 /* It is, get the name from the blob */
1720 /* Only accept this scenario if the caller wanted Aliases */
1721 if((RnrContext
->dwControlFlags
& LUP_RETURN_ALIASES
) &&
1722 (Blob
->AliasCount
> RnrContext
->Instance
))
1724 /* Get the name from the Alias */
1725 Name
= Blob
->Aliases
[RnrContext
->Instance
];
1727 /* Let the caller know that this is an Alias */
1728 /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */
1733 ErrorCode
= WSA_E_NO_MORE
;
1738 /* Lookups are complete... time to return the right stuff! */
1739 lpqsResults
->dwNameSpace
= NS_DNS
;
1741 /* Caller wants the Type back */
1742 if(RnrContext
->dwControlFlags
& LUP_RETURN_TYPE
)
1744 /* Copy into the flat buffer and point to it */
1745 lpqsResults
->lpServiceClassId
= FlatBuf_CopyMemory(&FlatBuffer
,
1746 &RnrContext
->lpServiceClassId
,
1751 /* Caller wants the Addreses Back */
1752 if((RnrContext
->dwControlFlags
& LUP_RETURN_ADDR
) && (Blob
))
1754 /* Build the CS Addr for the caller */
1755 ErrorCode
= BuildCsAddr(lpqsResults
,
1758 RnrContext
->UdpPort
,
1759 RnrContext
->TcpPort
,
1760 (RnrContext
->LookupFlags
& REVERSE
) == 1);
1763 /* Caller wants a Blob */
1764 if(RnrContext
->dwControlFlags
& LUP_RETURN_BLOB
)
1766 /* Save the current size and position */
1767 FreeSize
= FlatBuffer
.BufferFreeSize
;
1768 Position
= FlatBuffer
.BufferPos
;
1770 /* Allocate some space for the Public Blob */
1771 lpqsResults
->lpBlob
= FlatBuf_ReserveAlignDword(&FlatBuffer
,
1774 /* Check for a Cached Blob */
1775 if((RnrContext
->RrType
) && (RnrContext
->CachedBlob
.pBlobData
))
1777 /* We have a Cached Blob, use it */
1778 BlobSize
= RnrContext
->CachedBlob
.cbSize
;
1779 BlobData
= FlatBuf_ReserveAlignDword(&FlatBuffer
, BlobSize
);
1781 /* Copy into the blob */
1782 RtlCopyMemory(RnrContext
->CachedBlob
.pBlobData
,
1788 /* Create an ANSI Host Entry */
1789 BlobData
= SaBlob_CreateHostent(&FlatBuffer
.BufferPos
,
1790 &FlatBuffer
.BufferFreeSize
,
1797 else if ((RnrContext
->LookupFlags
& IANA
) && (ServEntry
))
1800 BlobData
= CopyServEntry(ServEntry
,
1801 &FlatBuffer
.BufferPos
,
1802 &FlatBuffer
.BufferFreeSize
,
1806 /* Manually update the buffer (no SaBlob function for servents) */
1807 FlatBuffer
.BufferPos
+= BlobSize
;
1808 FlatBuffer
.BufferFreeSize
-= BlobSize
;
1812 /* We have nothing to return! */
1814 lpqsResults
->lpBlob
= NULL
;
1815 FlatBuffer
.BufferPos
= Position
;
1816 FlatBuffer
.BufferFreeSize
= FreeSize
;
1819 /* Make sure we have a blob by here */
1823 lpqsResults
->lpBlob
->pBlobData
= BlobData
;
1824 lpqsResults
->lpBlob
->cbSize
= BlobSize
;
1828 /* Set the error code */
1829 ErrorCode
= WSAEFAULT
;
1833 /* Caller wants a name, and we have one */
1834 if((RnrContext
->dwControlFlags
& LUP_RETURN_NAME
) && (Name
))
1836 /* Check if we have an ANSI name */
1841 Dns_StringCopy(&UnicodeName
,
1850 /* Keep the name as is */
1851 UnicodeName
= (LPWSTR
)Name
;
1854 /* Write it to the buffer */
1855 Name
= FlatBuf_WriteString(&FlatBuffer
, UnicodeName
, TRUE
);
1857 /* Return it to the caller */
1858 lpqsResults
->lpszServiceInstanceName
= Name
;
1862 /* Check which path got us here */
1863 if (ErrorCode
!= NO_ERROR
)
1866 SetLastError(ErrorCode
);
1868 /* Check if was a memory error */
1869 if (ErrorCode
== WSAEFAULT
)
1871 /* Update buffer length */
1872 *lpdwBufferLength
-= (DWORD
)FlatBuffer
.BufferFreeSize
;
1874 /* Decrease an instance */
1875 RnrCtx_DecInstance(RnrContext
);
1878 /* Set the normalized error code */
1879 ErrorCode
= SOCKET_ERROR
;
1882 /* Release the RnR Context */
1883 RnrCtx_Release(RnrContext
);
1885 /* Return error code */
1890 * COPYRIGHT: See COPYING in the top level directory
1891 * PROJECT: ReactOS Winsock 2 SPI
1892 * FILE: lib/mswsock/lib/init.c
1893 * PURPOSE: DLL Initialization
1896 /* INCLUDES ******************************************************************/
1899 #define ALL_LUP_FLAGS (0x0BFFF)
1901 /* DATA **********************************************************************/
1903 LPWSTR g_pszHostName
;
1904 LPWSTR g_pszHostFqdn
;
1906 GUID NbtProviderId
= {0};
1907 GUID DNSProviderId
= {0};
1910 NSP_ROUTINE g_NspVector
= {sizeof(NSP_ROUTINE
),
1914 Dns_NSPLookupServiceBegin
,
1915 Dns_NSPLookupServiceNext
,
1916 Dns_NSPLookupServiceEnd
,
1918 Dns_NSPInstallServiceClass
,
1919 Dns_NSPRemoveServiceClass
,
1920 Dns_NSPGetServiceClassInfo
};
1922 /* FUNCTIONS *****************************************************************/
1926 Dns_NSPStartup(IN LPGUID lpProviderId
,
1927 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
1932 /* Validate the size */
1933 if (lpsnpRoutines
->cbSize
!= sizeof(NSP_ROUTINE
))
1936 SetLastError(WSAEINVALIDPROCTABLE
);
1937 return SOCKET_ERROR
;
1940 /* Enter the prolog */
1941 Prolog
= RNRPROV_SockEnterApi();
1944 /* Increase our reference count */
1945 InterlockedIncrement(&g_NspRefCount
);
1947 /* Check if we don't have the hostname */
1950 /* Query it from DNS */
1951 DnsQueryConfig(DnsConfigHostName_W
,
1952 DNS_CONFIG_FLAG_ALLOC
,
1959 /* Check if we have a hostname now, but not a Fully-Qualified Domain */
1960 if (g_pszHostName
&& !(g_pszHostFqdn
))
1962 /* Get the domain from DNS */
1963 DnsQueryConfig(DnsConfigFullHostName_W
,
1964 DNS_CONFIG_FLAG_ALLOC
,
1971 /* If we don't have both of them, then set error */
1972 if (!(g_pszHostName
) || !(g_pszHostFqdn
)) ErrorCode
= SOCKET_ERROR
;
1975 /* Check if the Prolog or DNS Local Queries failed */
1976 if (!(Prolog
) || (ErrorCode
!= NO_ERROR
))
1979 SetLastError(WSASYSNOTREADY
);
1980 return SOCKET_ERROR
;
1983 /* Copy the Routines */
1984 RtlMoveMemory(lpsnpRoutines
, &g_NspVector
, sizeof(NSP_ROUTINE
));
1986 /* Check if this is NBT or DNS */
1987 if (!memcmp(lpProviderId
, &NbtProviderId
, sizeof(GUID
)))
1989 /* Enable the NBT Mask */
1990 MaskOfGuids
|= NBT_MASK
;
1992 else if (!memcmp(lpProviderId
, &DNSProviderId
, sizeof(GUID
)))
1994 /* Enable the DNS Mask */
1995 MaskOfGuids
|= DNS_MASK
;
1998 /* Return success */
2004 Nsp_GlobalCleanup(VOID
)
2006 /* Cleanup the RnR Contexts */
2007 RnrCtx_ListCleanup();
2009 /* Free the hostnames, if we have them */
2010 if (g_pszHostName
) DnsApiFree(g_pszHostName
);
2011 if (g_pszHostFqdn
) DnsApiFree(g_pszHostFqdn
);
2012 g_pszHostFqdn
= g_pszHostName
= NULL
;
2017 NSPStartup(IN LPGUID lpProviderId
,
2018 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
2022 /* Initialize the DLL */
2023 ErrorCode
= MSWSOCK_Initialize();
2024 if (ErrorCode
!= NO_ERROR
)
2027 SetLastError(WSANOTINITIALISED
);
2028 return SOCKET_ERROR
;
2031 /* Check if this is Winsock Mobile or DNS */
2032 if (!memcmp(lpProviderId
, &gNLANamespaceGuid
, sizeof(GUID
)))
2034 /* Initialize WSM */
2035 return WSM_NSPStartup(lpProviderId
, lpsnpRoutines
);
2038 /* Initialize DNS */
2039 return Dns_NSPStartup(lpProviderId
, lpsnpRoutines
);
2044 Dns_NSPCleanup(IN LPGUID lpProviderId
)
2046 /* Decrement our reference count and do global cleanup if it's reached 0 */
2047 if (!(InterlockedDecrement(&g_NspRefCount
))) Nsp_GlobalCleanup();
2049 /* Return success */
2055 Dns_NSPSetService(IN LPGUID lpProviderId
,
2056 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
,
2057 IN LPWSAQUERYSETW lpqsRegInfo
,
2058 IN WSAESETSERVICEOP essOperation
,
2059 IN DWORD dwControlFlags
)
2061 /* Unlike NLA, DNS Services cannot be dynmically modified */
2062 SetLastError(ERROR_NOT_SUPPORTED
);
2063 return SOCKET_ERROR
;
2068 Dns_NSPInstallServiceClass(IN LPGUID lpProviderId
,
2069 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
2071 /* Unlike NLA, DNS Services cannot be dynmically modified */
2072 SetLastError(WSAEOPNOTSUPP
);
2073 return SOCKET_ERROR
;
2078 Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId
,
2079 IN LPGUID lpServiceCallId
)
2081 /* Unlike NLA, DNS Services cannot be dynmically modified */
2082 SetLastError(WSAEOPNOTSUPP
);
2083 return SOCKET_ERROR
;
2087 Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId
,
2088 IN OUT LPDWORD lpdwBufSize
,
2089 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
2091 /* Unlike NLA, DNS Services cannot be dynmically modified */
2092 SetLastError(WSAEOPNOTSUPP
);
2093 return SOCKET_ERROR
;
2098 Dns_NSPLookupServiceEnd(IN HANDLE hLookup
)
2100 PRNR_CONTEXT RnrContext
;
2102 /* Get this handle's context */
2103 RnrContext
= RnrCtx_Get(hLookup
, 0, NULL
);
2105 /* Mark it as completed */
2106 RnrContext
->LookupFlags
|= DONE
;
2108 /* Dereference it once for our _Get */
2109 RnrCtx_Release(RnrContext
);
2111 /* And once last to delete it */
2112 RnrCtx_Release(RnrContext
);
2120 rnr_IdForGuid(IN LPGUID Guid
)
2123 if (memcmp(Guid
, &InetHostName
, sizeof(GUID
))) return 0x10000002;
2124 if (memcmp(Guid
, &Ipv6Guid
, sizeof(GUID
))) return 0x10000023;
2125 if (memcmp(Guid
, &HostnameGuid
, sizeof(GUID
))) return 0x1;
2126 if (memcmp(Guid
, &AddressGuid
, sizeof(GUID
))) return 0x80000000;
2127 if (memcmp(Guid
, &IANAGuid
, sizeof(GUID
))) return 0x2;
2128 if IS_SVCID_DNS(Guid
) return 0x5000000;
2129 if IS_SVCID_TCP(Guid
) return 0x1000000;
2130 if IS_SVCID_UDP(Guid
) return 0x2000000;
2136 FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer
,
2139 /* Let DNSLIB do the grunt work */
2140 return FlatBuf_Arg_Reserve((PVOID
)FlatBuffer
->BufferPos
,
2141 &FlatBuffer
->BufferFreeSize
,
2148 FlatBuf_WriteString(IN PFLATBUFF FlatBuffer
,
2150 IN BOOLEAN IsUnicode
)
2152 /* Let DNSLIB do the grunt work */
2153 return FlatBuf_Arg_WriteString((PVOID
)FlatBuffer
->BufferPos
,
2154 &FlatBuffer
->BufferFreeSize
,
2161 FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer
,
2166 /* Let DNSLIB do the grunt work */
2167 return FlatBuf_Arg_CopyMemory((PVOID
)FlatBuffer
->BufferPos
,
2168 &FlatBuffer
->BufferFreeSize
,
2176 Dns_NSPLookupServiceBegin(LPGUID lpProviderId
,
2177 LPWSAQUERYSETW lpqsRestrictions
,
2178 LPWSASERVICECLASSINFOW lpServiceClassInfo
,
2179 DWORD dwControlFlags
,
2182 INT ErrorCode
= SOCKET_ERROR
;
2183 PWCHAR ServiceName
= lpqsRestrictions
->lpszServiceInstanceName
;
2184 LPGUID ServiceClassId
;
2186 ULONG LookupFlags
= 0;
2187 BOOL NameRequested
= FALSE
;
2188 WCHAR StringBuffer
[48];
2190 DWORD LocalProtocols
;
2191 ULONG ProtocolFlags
;
2192 PSERVENT LookupServent
;
2193 DWORD UdpPort
, TcpPort
;
2194 PRNR_CONTEXT RnrContext
;
2195 PSOCKADDR_IN ReverseSock
;
2197 /* Check if the Size isn't weird */
2198 if(lpqsRestrictions
->dwSize
< sizeof(WSAQUERYSETW
))
2200 ErrorCode
= WSAEFAULT
;
2205 ServiceClassId
= lpqsRestrictions
->lpServiceClassId
;
2209 ErrorCode
= WSA_INVALID_PARAMETER
;
2213 /* Get the RNR ID */
2214 RnrId
= rnr_IdForGuid(ServiceClassId
);
2216 /* Make sure that the control flags are valid */
2217 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
2218 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
2219 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
2221 /* Either non-recognized flags or invalid combos were passed */
2222 ErrorCode
= WSA_INVALID_PARAMETER
;
2226 /* Make sure that we have no context, and that LUP_CONTAINERS is not on */
2227 if(((lpqsRestrictions
->lpszContext
) &&
2228 (*lpqsRestrictions
->lpszContext
) &&
2229 (wcscmp(lpqsRestrictions
->lpszContext
, L
"\\"))) ||
2230 (dwControlFlags
& LUP_CONTAINERS
))
2232 /* We don't support contexts or LUP_CONTAINERS */
2233 ErrorCode
= WSANO_DATA
;
2237 /* Is this a Reverse Lookup? */
2238 if (RnrId
== 0x80000000)
2240 /* Remember for later */
2241 LookupFlags
= REVERSE
;
2245 /* Is this a IANA Lookup? */
2248 /* Mask out this flag since it's of no use now */
2249 dwControlFlags
&= ~(LUP_RETURN_ADDR
);
2251 /* This is a IANA lookup, remember for later */
2252 LookupFlags
|= IANA
;
2255 /* Check if we need a name or not */
2256 if ((RnrId
== 0x1) ||
2257 (RnrId
== 0x10000002) ||
2258 (RnrId
== 0x10000023) ||
2259 (RnrId
== 0x10000022))
2262 NameRequested
= TRUE
;
2266 /* Final check to make sure if we need a name or not */
2267 if (RnrId
& 0x3000000) NameRequested
= TRUE
;
2269 /* No Service Name was specified */
2270 if(!(ServiceName
) || !(*ServiceName
))
2273 * A name was requested but no Service Name was given,
2274 * so this is a local lookup
2278 /* A local Lookup */
2279 LookupFlags
|= LOCAL
;
2282 else if((LookupFlags
& REVERSE
) &&
2283 (lpqsRestrictions
->lpcsaBuffer
) &&
2284 (lpqsRestrictions
->dwNumberOfCsAddrs
== 1))
2286 /* Reverse lookup, make sure a CS Address is there */
2287 ReverseSock
= (struct sockaddr_in
*)
2288 lpqsRestrictions
->lpcsaBuffer
->RemoteAddr
.lpSockaddr
;
2290 /* Convert address to Unicode */
2291 MultiByteToWideChar(CP_ACP
,
2293 inet_ntoa(ReverseSock
->sin_addr
),
2298 /* Set it as the new name */
2299 ServiceName
= StringBuffer
;
2303 /* We can't do anything without a service name at this point */
2304 ErrorCode
= WSA_INVALID_PARAMETER
;
2308 else if(NameRequested
)
2310 /* Check for meaningful DNS Names */
2311 if (DnsNameCompare_W(ServiceName
, L
"localhost") ||
2312 DnsNameCompare_W(ServiceName
, L
"loopback"))
2314 /* This is the local and/or loopback DNS name */
2315 LookupFlags
|= (LOCAL
| LOOPBACK
);
2317 else if (DnsNameCompare_W(ServiceName
, g_pszHostName
) ||
2318 DnsNameCompare_W(ServiceName
, g_pszHostFqdn
))
2320 /* This is the local name of the computer */
2321 LookupFlags
|= LOCAL
;
2325 /* Check if any restrictions were made on the protocols */
2326 if(lpqsRestrictions
->lpafpProtocols
)
2328 /* Save our local copy to speed up the loop */
2329 LocalProtocols
= lpqsRestrictions
->dwNumberOfProtocols
;
2332 /* Loop the protocols */
2333 for(i
= 0; LocalProtocols
--;)
2335 /* Make sure it's a family that we recognize */
2336 if ((lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET
) ||
2337 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET6
) ||
2338 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_UNSPEC
) ||
2339 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_ATM
))
2341 /* Find which one is used */
2342 switch(lpqsRestrictions
->lpafpProtocols
[i
].iProtocol
)
2345 ProtocolFlags
|= UDP
;
2348 ProtocolFlags
|= TCP
;
2351 ProtocolFlags
|= ATM
;
2358 /* Make sure we have at least a valid protocol */
2362 ErrorCode
= WSANO_DATA
;
2368 /* No restrictions, assume TCP/UDP */
2369 ProtocolFlags
= (TCP
| UDP
);
2372 /* Create the Servent from the Service String */
2373 UdpPort
= TcpPort
= -1;
2374 ProtocolFlags
|= GetServerAndProtocolsFromString(lpqsRestrictions
->lpszQueryString
,
2378 /* Extract the port numbers */
2381 /* Are we using UDP? */
2382 if(ProtocolFlags
& UDP
)
2384 /* Get the UDP Port, disable the TCP Port */
2385 UdpPort
= ntohs(LookupServent
->s_port
);
2388 else if(ProtocolFlags
& TCP
)
2390 /* Get the TCP Port, disable the UDP Port */
2391 TcpPort
= ntohs(LookupServent
->s_port
);
2397 /* No servent, so use the Service ID to check */
2398 if(ProtocolFlags
& UDP
)
2400 /* Get the Port from the Service ID */
2401 UdpPort
= FetchPortFromClassInfo(UDP
,
2403 lpServiceClassInfo
);
2411 /* No servent, so use the Service ID to check */
2412 if(ProtocolFlags
& TCP
)
2414 /* Get the Port from the Service ID */
2415 UdpPort
= FetchPortFromClassInfo(TCP
,
2417 lpServiceClassInfo
);
2426 /* Check if we still don't have a valid port by now */
2427 if((TcpPort
== -1) && (UdpPort
== -1))
2429 /* Check if this is TCP */
2430 if ((ProtocolFlags
& TCP
) || !(ProtocolFlags
& UDP
))
2432 /* Set the UDP Port to 0 */
2437 /* Set the TCP Port to 0 */
2442 /* Allocate a Context for this Query */
2443 RnrContext
= RnrCtx_Create(NULL
, ServiceName
);
2444 RnrContext
->lpServiceClassId
= *ServiceClassId
;
2445 RnrContext
->RnrId
= RnrId
;
2446 RnrContext
->dwControlFlags
= dwControlFlags
;
2447 RnrContext
->TcpPort
= TcpPort
;
2448 RnrContext
->UdpPort
= UdpPort
;
2449 RnrContext
->LookupFlags
= LookupFlags
;
2450 RnrContext
->lpProviderId
= *lpProviderId
;
2451 RnrContext
->dwNameSpace
= lpqsRestrictions
->dwNameSpace
;
2452 RnrCtx_Release(RnrContext
);
2454 /* Return the context as a handle */
2455 *lphLookup
= (HANDLE
)RnrContext
;
2457 /* Check if this was a TCP, UDP or DNS Query */
2458 if(RnrId
& 0x3000000)
2460 /* Get the RR Type from the Service ID */
2461 RnrContext
->RrType
= RR_FROM_SVCID(ServiceClassId
);
2464 /* Return Success */
2465 ErrorCode
= ERROR_SUCCESS
;
2468 /* Check if we got here through a failure path */
2469 if (ErrorCode
!= ERROR_SUCCESS
)
2471 /* Set the last error and fail */
2472 SetLastError(ErrorCode
);
2473 return SOCKET_ERROR
;
2476 /* Return success */
2477 return ERROR_SUCCESS
;
2482 BuildCsAddr(IN LPWSAQUERYSETW QuerySet
,
2483 IN PFLATBUFF FlatBuffer
,
2487 IN BOOLEAN ReverseLookup
)
2494 Dns_NSPLookupServiceNext(IN HANDLE hLookup
,
2495 IN DWORD dwControlFlags
,
2496 IN OUT LPDWORD lpdwBufferLength
,
2497 OUT LPWSAQUERYSETW lpqsResults
)
2500 WSAQUERYSETW LocalResults
;
2502 PRNR_CONTEXT RnrContext
= NULL
;
2503 FLATBUFF FlatBuffer
;
2505 PDNS_BLOB Blob
= NULL
;
2507 PSERVENT ServEntry
= NULL
;
2508 PDNS_ARRAY DnsArray
;
2509 BOOLEAN IsUnicode
= TRUE
;
2513 PVOID BlobData
= NULL
;
2517 /* Make sure that the control flags are valid */
2518 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
2519 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
2520 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
2522 /* Either non-recognized flags or invalid combos were passed */
2523 ErrorCode
= WSA_INVALID_PARAMETER
;
2527 /* Get the Context */
2528 RnrContext
= RnrCtx_Get(hLookup
, dwControlFlags
, &Instance
);
2531 /* This lookup handle must be invalid */
2532 SetLastError(WSA_INVALID_HANDLE
);
2533 return SOCKET_ERROR
;
2536 /* Assume success for now */
2537 SetLastError(NO_ERROR
);
2539 /* Validate the query set size */
2540 if (*lpdwBufferLength
< sizeof(WSAQUERYSETW
))
2542 /* Windows doesn't fail, but sets up a local QS for you... */
2543 lpqsResults
= &LocalResults
;
2544 ErrorCode
= WSAEFAULT
;
2547 /* Zero out the buffer and fill out basic data */
2548 RtlZeroMemory(lpqsResults
, sizeof(WSAQUERYSETW
));
2549 lpqsResults
->dwNameSpace
= NS_DNS
;
2550 lpqsResults
->dwSize
= sizeof(WSAQUERYSETW
);
2552 /* Initialize the Buffer */
2553 FlatBuf_Init(&FlatBuffer
,
2555 (ULONG
)(*lpdwBufferLength
- sizeof(WSAQUERYSETW
)));
2557 /* Check if this is an IANA Lookup */
2558 if(RnrContext
->LookupFlags
& IANA
)
2560 /* Service Lookup */
2561 GetServerAndProtocolsFromString(RnrContext
->ServiceName
,
2562 (LPGUID
)&HostnameGuid
,
2566 PortNumber
= ntohs(ServEntry
->s_port
);
2568 /* Use this as the name */
2569 Name
= ServEntry
->s_name
;
2572 /* Override some parts of the Context and check for TCP/UDP */
2573 if(!_stricmp("tcp", ServEntry
->s_proto
))
2575 /* Set the TCP Guid */
2576 SET_TCP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
2577 RnrContext
->TcpPort
= PortNumber
;
2578 RnrContext
->UdpPort
= -1;
2582 /* Set the UDP Guid */
2583 SET_UDP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
2584 RnrContext
->UdpPort
= PortNumber
;
2585 RnrContext
->TcpPort
= -1;
2590 /* Check if the caller requested for RES_SERVICE */
2591 if(RnrContext
->dwControlFlags
& LUP_RES_SERVICE
)
2593 /* Make sure that this is the first instance */
2597 ErrorCode
= WSA_E_NO_MORE
;
2602 /* Create the blob */
2604 Blob
= SaBlob_CreateFromIp4(RnrContext
->ServiceName
,
2611 ErrorCode
= WSAEFAULT
;
2615 else if(!(Blob
= RnrContext
->CachedSaBlob
))
2617 /* An actual Host Lookup, but we don't have a cached HostEntry yet */
2618 if (!memcmp(&RnrContext
->lpServiceClassId
,
2620 sizeof(GUID
)) && !(RnrContext
->ServiceName
))
2622 /* Do a Regular DNS Lookup */
2623 Blob
= Rnr_DoHostnameLookup(RnrContext
);
2625 else if (RnrContext
->LookupFlags
& REVERSE
)
2627 /* Do a Reverse DNS Lookup */
2628 Blob
= Rnr_GetHostByAddr(RnrContext
);
2632 /* Do a Hostname Lookup */
2633 Blob
= Rnr_DoDnsLookup(RnrContext
);
2636 /* Check if we got a blob, and cache it */
2637 if (Blob
) RnrContext
->CachedSaBlob
= Blob
;
2640 /* We should have a blob by now */
2644 if (ErrorCode
== NO_ERROR
)
2646 /* Supposedly no error, so find it out */
2647 ErrorCode
= GetLastError();
2648 if (ErrorCode
== NO_ERROR
) ErrorCode
= WSASERVICE_NOT_FOUND
;
2656 /* Check if this is the first instance or not */
2657 if(!RnrContext
->Instance
)
2659 /* It is, get the name from the blob */
2664 /* Only accept this scenario if the caller wanted Aliases */
2665 if((RnrContext
->dwControlFlags
& LUP_RETURN_ALIASES
) &&
2666 (Blob
->AliasCount
> RnrContext
->Instance
))
2668 /* Get the name from the Alias */
2669 Name
= Blob
->Aliases
[RnrContext
->Instance
];
2671 /* Let the caller know that this is an Alias */
2672 /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */
2677 ErrorCode
= WSA_E_NO_MORE
;
2682 /* Lookups are complete... time to return the right stuff! */
2683 lpqsResults
->dwNameSpace
= NS_DNS
;
2685 /* Caller wants the Type back */
2686 if(RnrContext
->dwControlFlags
& LUP_RETURN_TYPE
)
2688 /* Copy into the flat buffer and point to it */
2689 lpqsResults
->lpServiceClassId
= FlatBuf_CopyMemory(&FlatBuffer
,
2690 &RnrContext
->lpServiceClassId
,
2695 /* Caller wants the Addreses Back */
2696 if((RnrContext
->dwControlFlags
& LUP_RETURN_ADDR
) && (Blob
))
2698 /* Build the CS Addr for the caller */
2699 ErrorCode
= BuildCsAddr(lpqsResults
,
2702 RnrContext
->UdpPort
,
2703 RnrContext
->TcpPort
,
2704 (RnrContext
->LookupFlags
& REVERSE
) == 1);
2707 /* Caller wants a Blob */
2708 if(RnrContext
->dwControlFlags
& LUP_RETURN_BLOB
)
2710 /* Save the current size and position */
2711 FreeSize
= FlatBuffer
.BufferFreeSize
;
2712 Position
= FlatBuffer
.BufferPos
;
2714 /* Allocate some space for the Public Blob */
2715 lpqsResults
->lpBlob
= FlatBuf_ReserveAlignDword(&FlatBuffer
,
2718 /* Check for a Cached Blob */
2719 if((RnrContext
->RrType
) && (RnrContext
->CachedBlob
.pBlobData
))
2721 /* We have a Cached Blob, use it */
2722 BlobSize
= RnrContext
->CachedBlob
.cbSize
;
2723 BlobData
= FlatBuf_ReserveAlignDword(&FlatBuffer
, BlobSize
);
2725 /* Copy into the blob */
2726 RtlCopyMemory(RnrContext
->CachedBlob
.pBlobData
,
2732 /* Create an ANSI Host Entry */
2733 BlobData
= SaBlob_CreateHostent(&FlatBuffer
.BufferPos
,
2734 &FlatBuffer
.BufferFreeSize
,
2741 else if ((RnrContext
->LookupFlags
& IANA
) && (ServEntry
))
2744 BlobData
= CopyServEntry(ServEntry
,
2745 &FlatBuffer
.BufferPos
,
2746 &FlatBuffer
.BufferFreeSize
,
2750 /* Manually update the buffer (no SaBlob function for servents) */
2751 FlatBuffer
.BufferPos
+= BlobSize
;
2752 FlatBuffer
.BufferFreeSize
-= BlobSize
;
2756 /* We have nothing to return! */
2758 lpqsResults
->lpBlob
= NULL
;
2759 FlatBuffer
.BufferPos
= Position
;
2760 FlatBuffer
.BufferFreeSize
= FreeSize
;
2763 /* Make sure we have a blob by here */
2767 lpqsResults
->lpBlob
->pBlobData
= BlobData
;
2768 lpqsResults
->lpBlob
->cbSize
= BlobSize
;
2772 /* Set the error code */
2773 ErrorCode
= WSAEFAULT
;
2777 /* Caller wants a name, and we have one */
2778 if((RnrContext
->dwControlFlags
& LUP_RETURN_NAME
) && (Name
))
2780 /* Check if we have an ANSI name */
2785 Dns_StringCopy(&UnicodeName
,
2794 /* Keep the name as is */
2795 UnicodeName
= (LPWSTR
)Name
;
2798 /* Write it to the buffer */
2799 Name
= FlatBuf_WriteString(&FlatBuffer
, UnicodeName
, TRUE
);
2801 /* Return it to the caller */
2802 lpqsResults
->lpszServiceInstanceName
= Name
;
2806 /* Check which path got us here */
2807 if (ErrorCode
!= NO_ERROR
)
2810 SetLastError(ErrorCode
);
2812 /* Check if was a memory error */
2813 if (ErrorCode
== WSAEFAULT
)
2815 /* Update buffer length */
2816 *lpdwBufferLength
-= (DWORD
)FlatBuffer
.BufferFreeSize
;
2818 /* Decrease an instance */
2819 RnrCtx_DecInstance(RnrContext
);
2822 /* Set the normalized error code */
2823 ErrorCode
= SOCKET_ERROR
;
2826 /* Release the RnR Context */
2827 RnrCtx_Release(RnrContext
);
2829 /* Return error code */
2834 * COPYRIGHT: See COPYING in the top level directory
2835 * PROJECT: ReactOS Winsock 2 SPI
2836 * FILE: lib/mswsock/lib/init.c
2837 * PURPOSE: DLL Initialization
2840 /* INCLUDES ******************************************************************/
2843 #define ALL_LUP_FLAGS (0x0BFFF)
2845 /* DATA **********************************************************************/
2847 LPWSTR g_pszHostName
;
2848 LPWSTR g_pszHostFqdn
;
2850 GUID NbtProviderId
= {0};
2851 GUID DNSProviderId
= {0};
2854 NSP_ROUTINE g_NspVector
= {sizeof(NSP_ROUTINE
),
2858 Dns_NSPLookupServiceBegin
,
2859 Dns_NSPLookupServiceNext
,
2860 Dns_NSPLookupServiceEnd
,
2862 Dns_NSPInstallServiceClass
,
2863 Dns_NSPRemoveServiceClass
,
2864 Dns_NSPGetServiceClassInfo
};
2866 /* FUNCTIONS *****************************************************************/
2870 Dns_NSPStartup(IN LPGUID lpProviderId
,
2871 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
2876 /* Validate the size */
2877 if (lpsnpRoutines
->cbSize
!= sizeof(NSP_ROUTINE
))
2880 SetLastError(WSAEINVALIDPROCTABLE
);
2881 return SOCKET_ERROR
;
2884 /* Enter the prolog */
2885 Prolog
= RNRPROV_SockEnterApi();
2888 /* Increase our reference count */
2889 InterlockedIncrement(&g_NspRefCount
);
2891 /* Check if we don't have the hostname */
2894 /* Query it from DNS */
2895 DnsQueryConfig(DnsConfigHostName_W
,
2896 DNS_CONFIG_FLAG_ALLOC
,
2903 /* Check if we have a hostname now, but not a Fully-Qualified Domain */
2904 if (g_pszHostName
&& !(g_pszHostFqdn
))
2906 /* Get the domain from DNS */
2907 DnsQueryConfig(DnsConfigFullHostName_W
,
2908 DNS_CONFIG_FLAG_ALLOC
,
2915 /* If we don't have both of them, then set error */
2916 if (!(g_pszHostName
) || !(g_pszHostFqdn
)) ErrorCode
= SOCKET_ERROR
;
2919 /* Check if the Prolog or DNS Local Queries failed */
2920 if (!(Prolog
) || (ErrorCode
!= NO_ERROR
))
2923 SetLastError(WSASYSNOTREADY
);
2924 return SOCKET_ERROR
;
2927 /* Copy the Routines */
2928 RtlMoveMemory(lpsnpRoutines
, &g_NspVector
, sizeof(NSP_ROUTINE
));
2930 /* Check if this is NBT or DNS */
2931 if (!memcmp(lpProviderId
, &NbtProviderId
, sizeof(GUID
)))
2933 /* Enable the NBT Mask */
2934 MaskOfGuids
|= NBT_MASK
;
2936 else if (!memcmp(lpProviderId
, &DNSProviderId
, sizeof(GUID
)))
2938 /* Enable the DNS Mask */
2939 MaskOfGuids
|= DNS_MASK
;
2942 /* Return success */
2948 Nsp_GlobalCleanup(VOID
)
2950 /* Cleanup the RnR Contexts */
2951 RnrCtx_ListCleanup();
2953 /* Free the hostnames, if we have them */
2954 if (g_pszHostName
) DnsApiFree(g_pszHostName
);
2955 if (g_pszHostFqdn
) DnsApiFree(g_pszHostFqdn
);
2956 g_pszHostFqdn
= g_pszHostName
= NULL
;
2961 NSPStartup(IN LPGUID lpProviderId
,
2962 IN OUT LPNSP_ROUTINE lpsnpRoutines
)
2966 /* Initialize the DLL */
2967 ErrorCode
= MSWSOCK_Initialize();
2968 if (ErrorCode
!= NO_ERROR
)
2971 SetLastError(WSANOTINITIALISED
);
2972 return SOCKET_ERROR
;
2975 /* Check if this is Winsock Mobile or DNS */
2976 if (!memcmp(lpProviderId
, &gNLANamespaceGuid
, sizeof(GUID
)))
2978 /* Initialize WSM */
2979 return WSM_NSPStartup(lpProviderId
, lpsnpRoutines
);
2982 /* Initialize DNS */
2983 return Dns_NSPStartup(lpProviderId
, lpsnpRoutines
);
2988 Dns_NSPCleanup(IN LPGUID lpProviderId
)
2990 /* Decrement our reference count and do global cleanup if it's reached 0 */
2991 if (!(InterlockedDecrement(&g_NspRefCount
))) Nsp_GlobalCleanup();
2993 /* Return success */
2999 Dns_NSPSetService(IN LPGUID lpProviderId
,
3000 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
,
3001 IN LPWSAQUERYSETW lpqsRegInfo
,
3002 IN WSAESETSERVICEOP essOperation
,
3003 IN DWORD dwControlFlags
)
3005 /* Unlike NLA, DNS Services cannot be dynmically modified */
3006 SetLastError(ERROR_NOT_SUPPORTED
);
3007 return SOCKET_ERROR
;
3012 Dns_NSPInstallServiceClass(IN LPGUID lpProviderId
,
3013 IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
3015 /* Unlike NLA, DNS Services cannot be dynmically modified */
3016 SetLastError(WSAEOPNOTSUPP
);
3017 return SOCKET_ERROR
;
3022 Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId
,
3023 IN LPGUID lpServiceCallId
)
3025 /* Unlike NLA, DNS Services cannot be dynmically modified */
3026 SetLastError(WSAEOPNOTSUPP
);
3027 return SOCKET_ERROR
;
3031 Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId
,
3032 IN OUT LPDWORD lpdwBufSize
,
3033 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
3035 /* Unlike NLA, DNS Services cannot be dynmically modified */
3036 SetLastError(WSAEOPNOTSUPP
);
3037 return SOCKET_ERROR
;
3042 Dns_NSPLookupServiceEnd(IN HANDLE hLookup
)
3044 PRNR_CONTEXT RnrContext
;
3046 /* Get this handle's context */
3047 RnrContext
= RnrCtx_Get(hLookup
, 0, NULL
);
3049 /* Mark it as completed */
3050 RnrContext
->LookupFlags
|= DONE
;
3052 /* Dereference it once for our _Get */
3053 RnrCtx_Release(RnrContext
);
3055 /* And once last to delete it */
3056 RnrCtx_Release(RnrContext
);
3064 rnr_IdForGuid(IN LPGUID Guid
)
3067 if (memcmp(Guid
, &InetHostName
, sizeof(GUID
))) return 0x10000002;
3068 if (memcmp(Guid
, &Ipv6Guid
, sizeof(GUID
))) return 0x10000023;
3069 if (memcmp(Guid
, &HostnameGuid
, sizeof(GUID
))) return 0x1;
3070 if (memcmp(Guid
, &AddressGuid
, sizeof(GUID
))) return 0x80000000;
3071 if (memcmp(Guid
, &IANAGuid
, sizeof(GUID
))) return 0x2;
3072 if IS_SVCID_DNS(Guid
) return 0x5000000;
3073 if IS_SVCID_TCP(Guid
) return 0x1000000;
3074 if IS_SVCID_UDP(Guid
) return 0x2000000;
3080 FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer
,
3083 /* Let DNSLIB do the grunt work */
3084 return FlatBuf_Arg_Reserve((PVOID
)FlatBuffer
->BufferPos
,
3085 &FlatBuffer
->BufferFreeSize
,
3092 FlatBuf_WriteString(IN PFLATBUFF FlatBuffer
,
3094 IN BOOLEAN IsUnicode
)
3096 /* Let DNSLIB do the grunt work */
3097 return FlatBuf_Arg_WriteString((PVOID
)FlatBuffer
->BufferPos
,
3098 &FlatBuffer
->BufferFreeSize
,
3105 FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer
,
3110 /* Let DNSLIB do the grunt work */
3111 return FlatBuf_Arg_CopyMemory((PVOID
)FlatBuffer
->BufferPos
,
3112 &FlatBuffer
->BufferFreeSize
,
3120 Dns_NSPLookupServiceBegin(LPGUID lpProviderId
,
3121 LPWSAQUERYSETW lpqsRestrictions
,
3122 LPWSASERVICECLASSINFOW lpServiceClassInfo
,
3123 DWORD dwControlFlags
,
3126 INT ErrorCode
= SOCKET_ERROR
;
3127 PWCHAR ServiceName
= lpqsRestrictions
->lpszServiceInstanceName
;
3128 LPGUID ServiceClassId
;
3130 ULONG LookupFlags
= 0;
3131 BOOL NameRequested
= FALSE
;
3132 WCHAR StringBuffer
[48];
3134 DWORD LocalProtocols
;
3135 ULONG ProtocolFlags
;
3136 PSERVENT LookupServent
;
3137 DWORD UdpPort
, TcpPort
;
3138 PRNR_CONTEXT RnrContext
;
3139 PSOCKADDR_IN ReverseSock
;
3141 /* Check if the Size isn't weird */
3142 if(lpqsRestrictions
->dwSize
< sizeof(WSAQUERYSETW
))
3144 ErrorCode
= WSAEFAULT
;
3149 ServiceClassId
= lpqsRestrictions
->lpServiceClassId
;
3153 ErrorCode
= WSA_INVALID_PARAMETER
;
3157 /* Get the RNR ID */
3158 RnrId
= rnr_IdForGuid(ServiceClassId
);
3160 /* Make sure that the control flags are valid */
3161 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
3162 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
3163 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
3165 /* Either non-recognized flags or invalid combos were passed */
3166 ErrorCode
= WSA_INVALID_PARAMETER
;
3170 /* Make sure that we have no context, and that LUP_CONTAINERS is not on */
3171 if(((lpqsRestrictions
->lpszContext
) &&
3172 (*lpqsRestrictions
->lpszContext
) &&
3173 (wcscmp(lpqsRestrictions
->lpszContext
, L
"\\"))) ||
3174 (dwControlFlags
& LUP_CONTAINERS
))
3176 /* We don't support contexts or LUP_CONTAINERS */
3177 ErrorCode
= WSANO_DATA
;
3181 /* Is this a Reverse Lookup? */
3182 if (RnrId
== 0x80000000)
3184 /* Remember for later */
3185 LookupFlags
= REVERSE
;
3189 /* Is this a IANA Lookup? */
3192 /* Mask out this flag since it's of no use now */
3193 dwControlFlags
&= ~(LUP_RETURN_ADDR
);
3195 /* This is a IANA lookup, remember for later */
3196 LookupFlags
|= IANA
;
3199 /* Check if we need a name or not */
3200 if ((RnrId
== 0x1) ||
3201 (RnrId
== 0x10000002) ||
3202 (RnrId
== 0x10000023) ||
3203 (RnrId
== 0x10000022))
3206 NameRequested
= TRUE
;
3210 /* Final check to make sure if we need a name or not */
3211 if (RnrId
& 0x3000000) NameRequested
= TRUE
;
3213 /* No Service Name was specified */
3214 if(!(ServiceName
) || !(*ServiceName
))
3217 * A name was requested but no Service Name was given,
3218 * so this is a local lookup
3222 /* A local Lookup */
3223 LookupFlags
|= LOCAL
;
3226 else if((LookupFlags
& REVERSE
) &&
3227 (lpqsRestrictions
->lpcsaBuffer
) &&
3228 (lpqsRestrictions
->dwNumberOfCsAddrs
== 1))
3230 /* Reverse lookup, make sure a CS Address is there */
3231 ReverseSock
= (struct sockaddr_in
*)
3232 lpqsRestrictions
->lpcsaBuffer
->RemoteAddr
.lpSockaddr
;
3234 /* Convert address to Unicode */
3235 MultiByteToWideChar(CP_ACP
,
3237 inet_ntoa(ReverseSock
->sin_addr
),
3242 /* Set it as the new name */
3243 ServiceName
= StringBuffer
;
3247 /* We can't do anything without a service name at this point */
3248 ErrorCode
= WSA_INVALID_PARAMETER
;
3252 else if(NameRequested
)
3254 /* Check for meaningful DNS Names */
3255 if (DnsNameCompare_W(ServiceName
, L
"localhost") ||
3256 DnsNameCompare_W(ServiceName
, L
"loopback"))
3258 /* This is the local and/or loopback DNS name */
3259 LookupFlags
|= (LOCAL
| LOOPBACK
);
3261 else if (DnsNameCompare_W(ServiceName
, g_pszHostName
) ||
3262 DnsNameCompare_W(ServiceName
, g_pszHostFqdn
))
3264 /* This is the local name of the computer */
3265 LookupFlags
|= LOCAL
;
3269 /* Check if any restrictions were made on the protocols */
3270 if(lpqsRestrictions
->lpafpProtocols
)
3272 /* Save our local copy to speed up the loop */
3273 LocalProtocols
= lpqsRestrictions
->dwNumberOfProtocols
;
3276 /* Loop the protocols */
3277 for(i
= 0; LocalProtocols
--;)
3279 /* Make sure it's a family that we recognize */
3280 if ((lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET
) ||
3281 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_INET6
) ||
3282 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_UNSPEC
) ||
3283 (lpqsRestrictions
->lpafpProtocols
[i
].iAddressFamily
== AF_ATM
))
3285 /* Find which one is used */
3286 switch(lpqsRestrictions
->lpafpProtocols
[i
].iProtocol
)
3289 ProtocolFlags
|= UDP
;
3292 ProtocolFlags
|= TCP
;
3295 ProtocolFlags
|= ATM
;
3302 /* Make sure we have at least a valid protocol */
3306 ErrorCode
= WSANO_DATA
;
3312 /* No restrictions, assume TCP/UDP */
3313 ProtocolFlags
= (TCP
| UDP
);
3316 /* Create the Servent from the Service String */
3317 UdpPort
= TcpPort
= -1;
3318 ProtocolFlags
|= GetServerAndProtocolsFromString(lpqsRestrictions
->lpszQueryString
,
3322 /* Extract the port numbers */
3325 /* Are we using UDP? */
3326 if(ProtocolFlags
& UDP
)
3328 /* Get the UDP Port, disable the TCP Port */
3329 UdpPort
= ntohs(LookupServent
->s_port
);
3332 else if(ProtocolFlags
& TCP
)
3334 /* Get the TCP Port, disable the UDP Port */
3335 TcpPort
= ntohs(LookupServent
->s_port
);
3341 /* No servent, so use the Service ID to check */
3342 if(ProtocolFlags
& UDP
)
3344 /* Get the Port from the Service ID */
3345 UdpPort
= FetchPortFromClassInfo(UDP
,
3347 lpServiceClassInfo
);
3355 /* No servent, so use the Service ID to check */
3356 if(ProtocolFlags
& TCP
)
3358 /* Get the Port from the Service ID */
3359 UdpPort
= FetchPortFromClassInfo(TCP
,
3361 lpServiceClassInfo
);
3370 /* Check if we still don't have a valid port by now */
3371 if((TcpPort
== -1) && (UdpPort
== -1))
3373 /* Check if this is TCP */
3374 if ((ProtocolFlags
& TCP
) || !(ProtocolFlags
& UDP
))
3376 /* Set the UDP Port to 0 */
3381 /* Set the TCP Port to 0 */
3386 /* Allocate a Context for this Query */
3387 RnrContext
= RnrCtx_Create(NULL
, ServiceName
);
3388 RnrContext
->lpServiceClassId
= *ServiceClassId
;
3389 RnrContext
->RnrId
= RnrId
;
3390 RnrContext
->dwControlFlags
= dwControlFlags
;
3391 RnrContext
->TcpPort
= TcpPort
;
3392 RnrContext
->UdpPort
= UdpPort
;
3393 RnrContext
->LookupFlags
= LookupFlags
;
3394 RnrContext
->lpProviderId
= *lpProviderId
;
3395 RnrContext
->dwNameSpace
= lpqsRestrictions
->dwNameSpace
;
3396 RnrCtx_Release(RnrContext
);
3398 /* Return the context as a handle */
3399 *lphLookup
= (HANDLE
)RnrContext
;
3401 /* Check if this was a TCP, UDP or DNS Query */
3402 if(RnrId
& 0x3000000)
3404 /* Get the RR Type from the Service ID */
3405 RnrContext
->RrType
= RR_FROM_SVCID(ServiceClassId
);
3408 /* Return Success */
3409 ErrorCode
= ERROR_SUCCESS
;
3412 /* Check if we got here through a failure path */
3413 if (ErrorCode
!= ERROR_SUCCESS
)
3415 /* Set the last error and fail */
3416 SetLastError(ErrorCode
);
3417 return SOCKET_ERROR
;
3420 /* Return success */
3421 return ERROR_SUCCESS
;
3426 BuildCsAddr(IN LPWSAQUERYSETW QuerySet
,
3427 IN PFLATBUFF FlatBuffer
,
3431 IN BOOLEAN ReverseLookup
)
3438 Dns_NSPLookupServiceNext(IN HANDLE hLookup
,
3439 IN DWORD dwControlFlags
,
3440 IN OUT LPDWORD lpdwBufferLength
,
3441 OUT LPWSAQUERYSETW lpqsResults
)
3444 WSAQUERYSETW LocalResults
;
3446 PRNR_CONTEXT RnrContext
= NULL
;
3447 FLATBUFF FlatBuffer
;
3449 PDNS_BLOB Blob
= NULL
;
3451 PSERVENT ServEntry
= NULL
;
3452 PDNS_ARRAY DnsArray
;
3453 BOOLEAN IsUnicode
= TRUE
;
3457 PVOID BlobData
= NULL
;
3461 /* Make sure that the control flags are valid */
3462 if ((dwControlFlags
& ~ALL_LUP_FLAGS
) ||
3463 ((dwControlFlags
& (LUP_CONTAINERS
| LUP_NOCONTAINERS
)) ==
3464 (LUP_CONTAINERS
| LUP_NOCONTAINERS
)))
3466 /* Either non-recognized flags or invalid combos were passed */
3467 ErrorCode
= WSA_INVALID_PARAMETER
;
3471 /* Get the Context */
3472 RnrContext
= RnrCtx_Get(hLookup
, dwControlFlags
, &Instance
);
3475 /* This lookup handle must be invalid */
3476 SetLastError(WSA_INVALID_HANDLE
);
3477 return SOCKET_ERROR
;
3480 /* Assume success for now */
3481 SetLastError(NO_ERROR
);
3483 /* Validate the query set size */
3484 if (*lpdwBufferLength
< sizeof(WSAQUERYSETW
))
3486 /* Windows doesn't fail, but sets up a local QS for you... */
3487 lpqsResults
= &LocalResults
;
3488 ErrorCode
= WSAEFAULT
;
3491 /* Zero out the buffer and fill out basic data */
3492 RtlZeroMemory(lpqsResults
, sizeof(WSAQUERYSETW
));
3493 lpqsResults
->dwNameSpace
= NS_DNS
;
3494 lpqsResults
->dwSize
= sizeof(WSAQUERYSETW
);
3496 /* Initialize the Buffer */
3497 FlatBuf_Init(&FlatBuffer
,
3499 (ULONG
)(*lpdwBufferLength
- sizeof(WSAQUERYSETW
)));
3501 /* Check if this is an IANA Lookup */
3502 if(RnrContext
->LookupFlags
& IANA
)
3504 /* Service Lookup */
3505 GetServerAndProtocolsFromString(RnrContext
->ServiceName
,
3506 (LPGUID
)&HostnameGuid
,
3510 PortNumber
= ntohs(ServEntry
->s_port
);
3512 /* Use this as the name */
3513 Name
= ServEntry
->s_name
;
3516 /* Override some parts of the Context and check for TCP/UDP */
3517 if(!_stricmp("tcp", ServEntry
->s_proto
))
3519 /* Set the TCP Guid */
3520 SET_TCP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
3521 RnrContext
->TcpPort
= PortNumber
;
3522 RnrContext
->UdpPort
= -1;
3526 /* Set the UDP Guid */
3527 SET_UDP_SVCID(&RnrContext
->lpServiceClassId
, PortNumber
);
3528 RnrContext
->UdpPort
= PortNumber
;
3529 RnrContext
->TcpPort
= -1;
3534 /* Check if the caller requested for RES_SERVICE */
3535 if(RnrContext
->dwControlFlags
& LUP_RES_SERVICE
)
3537 /* Make sure that this is the first instance */
3541 ErrorCode
= WSA_E_NO_MORE
;
3546 /* Create the blob */
3548 Blob
= SaBlob_CreateFromIp4(RnrContext
->ServiceName
,
3555 ErrorCode
= WSAEFAULT
;
3559 else if(!(Blob
= RnrContext
->CachedSaBlob
))
3561 /* An actual Host Lookup, but we don't have a cached HostEntry yet */
3562 if (!memcmp(&RnrContext
->lpServiceClassId
,
3564 sizeof(GUID
)) && !(RnrContext
->ServiceName
))
3566 /* Do a Regular DNS Lookup */
3567 Blob
= Rnr_DoHostnameLookup(RnrContext
);
3569 else if (RnrContext
->LookupFlags
& REVERSE
)
3571 /* Do a Reverse DNS Lookup */
3572 Blob
= Rnr_GetHostByAddr(RnrContext
);
3576 /* Do a Hostname Lookup */
3577 Blob
= Rnr_DoDnsLookup(RnrContext
);
3580 /* Check if we got a blob, and cache it */
3581 if (Blob
) RnrContext
->CachedSaBlob
= Blob
;
3584 /* We should have a blob by now */
3588 if (ErrorCode
== NO_ERROR
)
3590 /* Supposedly no error, so find it out */
3591 ErrorCode
= GetLastError();
3592 if (ErrorCode
== NO_ERROR
) ErrorCode
= WSASERVICE_NOT_FOUND
;
3600 /* Check if this is the first instance or not */
3601 if(!RnrContext
->Instance
)
3603 /* It is, get the name from the blob */
3608 /* Only accept this scenario if the caller wanted Aliases */
3609 if((RnrContext
->dwControlFlags
& LUP_RETURN_ALIASES
) &&
3610 (Blob
->AliasCount
> RnrContext
->Instance
))
3612 /* Get the name from the Alias */
3613 Name
= Blob
->Aliases
[RnrContext
->Instance
];
3615 /* Let the caller know that this is an Alias */
3616 /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */
3621 ErrorCode
= WSA_E_NO_MORE
;
3626 /* Lookups are complete... time to return the right stuff! */
3627 lpqsResults
->dwNameSpace
= NS_DNS
;
3629 /* Caller wants the Type back */
3630 if(RnrContext
->dwControlFlags
& LUP_RETURN_TYPE
)
3632 /* Copy into the flat buffer and point to it */
3633 lpqsResults
->lpServiceClassId
= FlatBuf_CopyMemory(&FlatBuffer
,
3634 &RnrContext
->lpServiceClassId
,
3639 /* Caller wants the Addreses Back */
3640 if((RnrContext
->dwControlFlags
& LUP_RETURN_ADDR
) && (Blob
))
3642 /* Build the CS Addr for the caller */
3643 ErrorCode
= BuildCsAddr(lpqsResults
,
3646 RnrContext
->UdpPort
,
3647 RnrContext
->TcpPort
,
3648 (RnrContext
->LookupFlags
& REVERSE
) == 1);
3651 /* Caller wants a Blob */
3652 if(RnrContext
->dwControlFlags
& LUP_RETURN_BLOB
)
3654 /* Save the current size and position */
3655 FreeSize
= FlatBuffer
.BufferFreeSize
;
3656 Position
= FlatBuffer
.BufferPos
;
3658 /* Allocate some space for the Public Blob */
3659 lpqsResults
->lpBlob
= FlatBuf_ReserveAlignDword(&FlatBuffer
,
3662 /* Check for a Cached Blob */
3663 if((RnrContext
->RrType
) && (RnrContext
->CachedBlob
.pBlobData
))
3665 /* We have a Cached Blob, use it */
3666 BlobSize
= RnrContext
->CachedBlob
.cbSize
;
3667 BlobData
= FlatBuf_ReserveAlignDword(&FlatBuffer
, BlobSize
);
3669 /* Copy into the blob */
3670 RtlCopyMemory(RnrContext
->CachedBlob
.pBlobData
,
3676 /* Create an ANSI Host Entry */
3677 BlobData
= SaBlob_CreateHostent(&FlatBuffer
.BufferPos
,
3678 &FlatBuffer
.BufferFreeSize
,
3685 else if ((RnrContext
->LookupFlags
& IANA
) && (ServEntry
))
3688 BlobData
= CopyServEntry(ServEntry
,
3689 &FlatBuffer
.BufferPos
,
3690 &FlatBuffer
.BufferFreeSize
,
3694 /* Manually update the buffer (no SaBlob function for servents) */
3695 FlatBuffer
.BufferPos
+= BlobSize
;
3696 FlatBuffer
.BufferFreeSize
-= BlobSize
;
3700 /* We have nothing to return! */
3702 lpqsResults
->lpBlob
= NULL
;
3703 FlatBuffer
.BufferPos
= Position
;
3704 FlatBuffer
.BufferFreeSize
= FreeSize
;
3707 /* Make sure we have a blob by here */
3711 lpqsResults
->lpBlob
->pBlobData
= BlobData
;
3712 lpqsResults
->lpBlob
->cbSize
= BlobSize
;
3716 /* Set the error code */
3717 ErrorCode
= WSAEFAULT
;
3721 /* Caller wants a name, and we have one */
3722 if((RnrContext
->dwControlFlags
& LUP_RETURN_NAME
) && (Name
))
3724 /* Check if we have an ANSI name */
3729 Dns_StringCopy(&UnicodeName
,
3738 /* Keep the name as is */
3739 UnicodeName
= (LPWSTR
)Name
;
3742 /* Write it to the buffer */
3743 Name
= FlatBuf_WriteString(&FlatBuffer
, UnicodeName
, TRUE
);
3745 /* Return it to the caller */
3746 lpqsResults
->lpszServiceInstanceName
= Name
;
3750 /* Check which path got us here */
3751 if (ErrorCode
!= NO_ERROR
)
3754 SetLastError(ErrorCode
);
3756 /* Check if was a memory error */
3757 if (ErrorCode
== WSAEFAULT
)
3759 /* Update buffer length */
3760 *lpdwBufferLength
-= (DWORD
)FlatBuffer
.BufferFreeSize
;
3762 /* Decrease an instance */
3763 RnrCtx_DecInstance(RnrContext
);
3766 /* Set the normalized error code */
3767 ErrorCode
= SOCKET_ERROR
;
3770 /* Release the RnR Context */
3771 RnrCtx_Release(RnrContext
);
3773 /* Return error code */