2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
5 * PURPOSE: Get X by Y Functions for Name Resolution.
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 AFPROTOCOLS afp
[2] = {{AF_INET
, IPPROTO_UDP
}, {AF_INET
, IPPROTO_TCP
}};
20 /* FUNCTIONS *****************************************************************/
27 /* Make sure it's valid */
32 /* Get the right base */
33 Addr
= *List
= (PCHAR
*)(((ULONG_PTR
)*List
+ Base
));
35 /* Loop the pointers */
39 *Addr
= (PCHAR
)(((ULONG_PTR
)*Addr
+ Base
));
47 UnpackServEnt(PSERVENT Servent
)
49 ULONG_PTR ServentPtr
= (ULONG_PTR
)Servent
;
51 /* Convert all the List Offsets to Pointers */
52 FixList(&Servent
->s_aliases
, ServentPtr
);
54 /* Convert the Name and Protocol Offesets to Pointers */
55 Servent
->s_name
= (PCHAR
)(Servent
->s_name
+ ServentPtr
);
56 Servent
->s_proto
= (PCHAR
)(Servent
->s_proto
+ ServentPtr
);
61 UnpackHostEnt(PHOSTENT Hostent
)
63 ULONG_PTR HostentPtr
= (ULONG_PTR
)Hostent
;
65 /* Convert the Name Offset to a Pointer */
66 if(Hostent
->h_name
) Hostent
->h_name
= (PCHAR
)(Hostent
->h_name
+ HostentPtr
);
68 /* Convert all the List Offsets to Pointers */
69 FixList(&Hostent
->h_aliases
, HostentPtr
);
70 FixList(&Hostent
->h_addr_list
, HostentPtr
);
75 Local_Ip4AddresstoString(IN PCHAR AddressBuffer
,
78 /* Convert the address into IPv4 format */
79 sprintf(AddressBuffer
, "%u.%u.%u.%u",
80 ((unsigned)Address
[0] & 0xff),
81 ((unsigned)Address
[1] & 0xff),
82 ((unsigned)Address
[2] & 0xff),
83 ((unsigned)Address
[3] & 0xff));
88 Local_Ip6AddresstoString(IN PCHAR AddressBuffer
,
93 /* Convert the address into IPv6 format */
94 for (i
= 0; i
< 8; i
++)
96 sprintf(AddressBuffer
, "%x:",
97 ((unsigned)Address
[0] & 0xff));
103 getxyDataEnt(IN OUT PCHAR
*Results
,
109 PWSAQUERYSETA WsaQuery
= (PWSAQUERYSETA
)*Results
;
115 /* Assume empty return name */
116 if (NewName
) *NewName
= NULL
;
118 /* Set up the Winsock Service Query */
119 RtlZeroMemory(WsaQuery
, sizeof(*WsaQuery
));
120 WsaQuery
->dwSize
= sizeof(*WsaQuery
);
121 WsaQuery
->lpszServiceInstanceName
= Name
;
122 WsaQuery
->lpServiceClassId
= (LPGUID
)Type
;
123 WsaQuery
->dwNameSpace
= NS_ALL
;
124 WsaQuery
->dwNumberOfProtocols
= 2;
125 WsaQuery
->lpafpProtocols
= &afp
[0];
127 /* Send the Query Request to find a Service */
128 ErrorCode
= WSALookupServiceBeginA(WsaQuery
,
129 LUP_RETURN_BLOB
| LUP_RETURN_NAME
,
132 if(ErrorCode
== ERROR_SUCCESS
)
136 /* Service was found, send the real query */
137 ErrorCode
= WSALookupServiceNextA(RnRHandle
,
142 /* Return the information requested */
143 if(ErrorCode
== ERROR_SUCCESS
)
145 /* Get the Blob and check if we have one */
146 Blob
= WsaQuery
->lpBlob
;
149 /* Did they want the name back? */
150 if(NewName
) *NewName
= WsaQuery
->lpszServiceInstanceName
;
154 /* Check if this was a Hostname lookup */
155 if (Type
== &HostnameGuid
)
157 /* Return the name anyways */
158 if(NewName
) *NewName
= WsaQuery
->lpszServiceInstanceName
;
162 /* We don't have a blob, sorry */
163 ErrorCode
= WSANO_DATA
;
169 /* WSALookupServiceEnd will set its own error, so save ours */
170 ErrorCode
= GetLastError();
172 /* Check if we failed because of missing buffer space */
173 if ((ErrorCode
== WSAEFAULT
) && (Length
> RNR_BUFFER_SIZE
))
175 /* Allocate a new buffer */
176 NewResults
= HeapAlloc(WsSockHeap
, 0, Length
);
179 /* Tell the caller his new buffer */
180 *Results
= NewResults
;
182 /* Update the WSA Query's location */
183 WsaQuery
= (PWSAQUERYSETA
)NewResults
;
190 /* No memory to allocate the new buffer */
191 ErrorCode
= WSA_NOT_ENOUGH_MEMORY
;
196 /* Finish the Query Request */
197 WSALookupServiceEnd(RnRHandle
);
199 /* Now set the Last Error */
200 if(ErrorCode
!= ERROR_SUCCESS
) SetLastError(ErrorCode
);
207 /* Return the blob */
216 gethostbyname(IN
const char FAR
* name
)
221 CHAR ResultsBuffer
[RNR_BUFFER_SIZE
];
222 PCHAR Results
= ResultsBuffer
;
223 CHAR szLocalName
[200];
227 DPRINT("gethostbyname: %s\n", name
);
230 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
233 SetLastError(ErrorCode
);
237 /* Check if no name was given */
240 /* This means we should do a local lookup first */
241 if(gethostname(szLocalName
, 200) != NO_ERROR
) return(NULL
);
242 pszName
= szLocalName
;
246 /* Use the name tha twas given to us */
247 pszName
= (PCHAR
)name
;
250 /* Get the Hostname in a Blob Structure */
251 Blob
= getxyDataEnt(&Results
,
257 /* Check if we didn't get a blob, or if we got an empty name */
258 if (!(Blob
) && (!(name
) || !(*name
)))
260 /* Try a new query */
261 Blob
= getxyDataEnt(&Results
,
268 /* Check if we got a blob */
271 /* Copy the blob to our buffer and convert it */
272 Hostent
= WsThreadBlobToHostent(Thread
, Blob
);
274 /* Unpack the hostent */
275 if(Hostent
) UnpackHostEnt(Hostent
);
279 /* We failed, so zero it out */
282 /* Normalize the error message */
283 if(GetLastError() == WSASERVICE_NOT_FOUND
)
285 SetLastError(WSAHOST_NOT_FOUND
);
289 /* Check if we received a newly allocated buffer; free it. */
290 if (Results
!= ResultsBuffer
) HeapFree(WsSockHeap
, 0, Results
);
292 /* Notify RAS Auto-dial helper */
293 if (Hostent
) WSNoteSuccessfulHostentLookup(name
, *Hostent
->h_addr
);
295 /* Return the hostent */
304 gethostbyaddr(IN
const char FAR
* addr
,
308 CHAR AddressBuffer
[100];
311 CHAR ResultsBuffer
[RNR_BUFFER_SIZE
];
312 PCHAR Results
= ResultsBuffer
;
316 DPRINT("gethostbyaddr: %s\n", addr
);
319 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
322 SetLastError(ErrorCode
);
326 /* Check for valid address pointer */
330 SetLastError(WSAEINVAL
);
334 /* Check which type it is */
337 /* Use IPV4 Address to String */
338 Local_Ip4AddresstoString(AddressBuffer
, (PCHAR
)addr
);
340 else if (type
== AF_INET6
)
342 /* Use IPV6 Address to String */
343 Local_Ip6AddresstoString(AddressBuffer
, (PCHAR
)addr
);
347 /* Invalid address type; fail */
348 SetLastError(WSAEINVAL
);
352 /* Get the Hostname in a Blob Structure */
353 Blob
= getxyDataEnt(&Results
,
359 /* Check if we got a blob */
362 /* Copy the blob to our buffer and convert it */
363 Hostent
= WsThreadBlobToHostent(Thread
, Blob
);
365 /* Unpack the hostent */
366 if(Hostent
) UnpackHostEnt(Hostent
);
370 /* We failed, so zero it out */
373 /* Normalize the error message */
374 if(GetLastError() == WSASERVICE_NOT_FOUND
)
376 SetLastError(WSAHOST_NOT_FOUND
);
380 /* Check if we received a newly allocated buffer; free it. */
381 if (Results
!= ResultsBuffer
) HeapFree(WsSockHeap
, 0, Results
);
383 /* Return the hostent */
392 gethostname(OUT
char FAR
* name
,
396 CHAR ResultsBuffer
[RNR_BUFFER_SIZE
];
397 PCHAR Results
= ResultsBuffer
;
398 DPRINT("gethostname: %p\n", name
);
400 /* Get the Hostname in a String */
401 if(getxyDataEnt(&Results
, RNR_BUFFER_SIZE
, NULL
, &HostnameGuid
, &Name
))
404 strcpy((LPSTR
)name
, Name
);
407 /* Check if we received a newly allocated buffer; free it. */
408 if (Results
!= ResultsBuffer
) HeapFree(WsSockHeap
, 0, Results
);
411 return ERROR_SUCCESS
;
419 getservbyport(IN
int port
,
420 IN
const char FAR
* proto
)
424 CHAR ResultsBuffer
[RNR_BUFFER_SIZE
];
425 PCHAR Results
= ResultsBuffer
;
430 DPRINT("getservbyport: %s\n", proto
);
433 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
436 SetLastError(ErrorCode
);
440 /* No protocol specifed */
441 if(!proto
) proto
= "";
443 /* Allocate memory for the port name */
444 PortName
= HeapAlloc(WsSockHeap
, 0, strlen(proto
) + 1 + 1 + 5);
448 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
452 /* Put it into the right syntax */
453 sprintf(PortName
, "%d/%s", (port
& 0xffff), proto
);
455 /* Get the Service in a Blob */
456 Blob
= getxyDataEnt(&Results
, RNR_BUFFER_SIZE
, PortName
, &IANAGuid
, 0);
458 /* Free the string we sent */
459 HeapFree(WsSockHeap
, 0, PortName
);
461 /* Check if we got a blob */
464 /* Copy the blob to our buffer and convert it */
465 Servent
= WsThreadBlobToServent(Thread
, Blob
);
467 /* Unpack the hostent */
468 if(Servent
) UnpackServEnt(Servent
);
472 /* We failed, so zero it out */
475 /* Normalize the error message */
476 if(GetLastError() == WSATYPE_NOT_FOUND
) SetLastError(WSANO_DATA
);
479 /* Check if we received a newly allocated buffer; free it. */
480 if (Results
!= ResultsBuffer
) HeapFree(WsSockHeap
, 0, Results
);
482 /* Return the hostent */
491 getservbyname(IN
const char FAR
* name
,
492 IN
const char FAR
* proto
)
496 CHAR ResultsBuffer
[RNR_BUFFER_SIZE
];
497 PCHAR Results
= ResultsBuffer
;
502 DPRINT("getservbyname: %s\n", name
);
505 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
508 SetLastError(ErrorCode
);
512 /* No protocol specifed */
513 if(!proto
) proto
= "";
515 /* Allocate buffer for it */
516 PortName
= HeapAlloc(WsSockHeap
, 0, strlen(proto
) + 1 + strlen(name
) + 1);
520 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
524 /* Put it into the right syntax */
525 sprintf(PortName
, "%s/%s", name
, proto
);
527 /* Get the Service in a Blob */
528 Blob
= getxyDataEnt(&Results
, RNR_BUFFER_SIZE
, PortName
, &IANAGuid
, 0);
530 /* Free the string we sent */
531 HeapFree(WsSockHeap
, 0, PortName
);
533 /* Check if we got a blob */
536 /* Copy the blob to our buffer and convert it */
537 Servent
= WsThreadBlobToServent(Thread
, Blob
);
539 /* Unpack the hostent */
540 if(Servent
) UnpackServEnt(Servent
);
544 /* We failed, so zero it out */
547 /* Normalize the error message */
548 if(GetLastError() == WSATYPE_NOT_FOUND
) SetLastError(WSANO_DATA
);
551 /* Check if we received a newly allocated buffer; free it. */
552 if (Results
!= ResultsBuffer
) HeapFree(WsSockHeap
, 0, Results
);
554 /* Return the hostent */
563 WSAAsyncGetHostByAddr(IN HWND hWnd
,
565 IN CONST CHAR FAR
*Address
,
568 OUT CHAR FAR
*Buffer
,
575 PWSASYNCBLOCK AsyncBlock
;
577 DPRINT("WSAAsyncGetHostByAddr: %lx, %lx, %s\n", hWnd
, wMsg
, Address
);
580 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
583 SetLastError(ErrorCode
);
587 /* Initialize the Async Thread */
588 if (!WsAsyncCheckAndInitThread())
591 SetLastError(WSAENOBUFS
);
595 /* Allocate an async block */
596 if (!(AsyncBlock
= WsAsyncAllocateBlock(Length
)))
599 SetLastError(WSAENOBUFS
);
603 /* Make a copy of the address */
604 AddressCopy
= AsyncBlock
+ 1;
605 RtlMoveMemory(AddressCopy
, Address
, Length
);
607 /* Initialize the Async Block */
608 AsyncBlock
->Operation
= WsAsyncGetHostByAddr
;
609 AsyncBlock
->GetHost
.hWnd
= hWnd
;
610 AsyncBlock
->GetHost
.wMsg
= wMsg
;
611 AsyncBlock
->GetHost
.ByWhat
= AddressCopy
;
612 AsyncBlock
->GetHost
.Length
= Length
;
613 AsyncBlock
->GetHost
.Type
= Type
;
614 AsyncBlock
->GetHost
.Buffer
= Buffer
;
615 AsyncBlock
->GetHost
.BufferLength
= BufferLength
;
617 /* Save the task handle and queue the request */
618 TaskHandle
= AsyncBlock
->TaskHandle
;
619 WsAsyncQueueRequest(AsyncBlock
);
621 /* Return the task handle */
630 WSAAsyncGetHostByName(IN HWND hWnd
,
632 IN CONST CHAR FAR
*Name
,
633 OUT CHAR FAR
*Buffer
,
639 PWSASYNCBLOCK AsyncBlock
;
642 DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd
, wMsg
, Name
);
645 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
648 SetLastError(ErrorCode
);
652 /* Initialize the Async Thread */
653 if (!WsAsyncCheckAndInitThread())
656 SetLastError(WSAENOBUFS
);
660 /* Allocate an async block */
661 if (!(AsyncBlock
= WsAsyncAllocateBlock(strlen(Name
) + sizeof(CHAR
))))
664 SetLastError(WSAENOBUFS
);
668 /* Make a copy of the address */
669 NameCopy
= AsyncBlock
+ 1;
670 strcpy(NameCopy
, Name
);
672 /* Initialize the Async Block */
673 AsyncBlock
->Operation
= WsAsyncGetHostByName
;
674 AsyncBlock
->GetHost
.hWnd
= hWnd
;
675 AsyncBlock
->GetHost
.wMsg
= wMsg
;
676 AsyncBlock
->GetHost
.ByWhat
= NameCopy
;
677 AsyncBlock
->GetHost
.Buffer
= Buffer
;
678 AsyncBlock
->GetHost
.BufferLength
= BufferLength
;
680 /* Save the task handle and queue the request */
681 TaskHandle
= AsyncBlock
->TaskHandle
;
682 WsAsyncQueueRequest(AsyncBlock
);
684 /* Return the task handle */
693 WSAAsyncGetProtoByName(IN HWND hWnd
,
695 IN CONST CHAR FAR
*Name
,
696 OUT CHAR FAR
*Buffer
,
702 PWSASYNCBLOCK AsyncBlock
;
705 DPRINT("WSAAsyncGetProtoByName: %lx, %lx, %s\n", hWnd
, wMsg
, Name
);
708 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
711 SetLastError(ErrorCode
);
715 /* Initialize the Async Thread */
716 if (!WsAsyncCheckAndInitThread())
719 SetLastError(WSAENOBUFS
);
723 /* Allocate an async block */
724 if (!(AsyncBlock
= WsAsyncAllocateBlock(strlen(Name
) + sizeof(CHAR
))))
727 SetLastError(WSAENOBUFS
);
731 /* Make a copy of the address */
732 NameCopy
= AsyncBlock
+ 1;
733 strcpy(NameCopy
, Name
);
735 /* Initialize the Async Block */
736 AsyncBlock
->Operation
= WsAsyncGetProtoByName
;
737 AsyncBlock
->GetProto
.hWnd
= hWnd
;
738 AsyncBlock
->GetProto
.wMsg
= wMsg
;
739 AsyncBlock
->GetProto
.ByWhat
= NameCopy
;
740 AsyncBlock
->GetProto
.Buffer
= Buffer
;
741 AsyncBlock
->GetProto
.BufferLength
= BufferLength
;
743 /* Save the task handle and queue the request */
744 TaskHandle
= AsyncBlock
->TaskHandle
;
745 WsAsyncQueueRequest(AsyncBlock
);
747 /* Return the task handle */
756 WSAAsyncGetProtoByNumber(IN HWND hWnd
,
759 OUT CHAR FAR
* Buffer
,
765 PWSASYNCBLOCK AsyncBlock
;
767 DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd
, wMsg
, Number
);
770 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
773 SetLastError(ErrorCode
);
777 /* Initialize the Async Thread */
778 if (!WsAsyncCheckAndInitThread())
781 SetLastError(WSAENOBUFS
);
785 /* Allocate an async block */
786 if (!(AsyncBlock
= WsAsyncAllocateBlock(0)))
789 SetLastError(WSAENOBUFS
);
793 /* Initialize the Async Block */
794 AsyncBlock
->Operation
= WsAsyncGetProtoByNumber
;
795 AsyncBlock
->GetProto
.hWnd
= hWnd
;
796 AsyncBlock
->GetProto
.wMsg
= wMsg
;
797 AsyncBlock
->GetProto
.ByWhat
= UlongToPtr(Number
);
798 AsyncBlock
->GetProto
.Buffer
= Buffer
;
799 AsyncBlock
->GetProto
.BufferLength
= BufferLength
;
801 /* Save the task handle and queue the request */
802 TaskHandle
= AsyncBlock
->TaskHandle
;
803 WsAsyncQueueRequest(AsyncBlock
);
805 /* Return the task handle */
814 WSAAsyncGetServByName(IN HWND hWnd
,
816 IN CONST CHAR FAR
*Name
,
817 IN CONST CHAR FAR
*Protocol
,
818 OUT CHAR FAR
*Buffer
,
824 PWSASYNCBLOCK AsyncBlock
;
827 DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd
, wMsg
, Name
);
830 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
833 SetLastError(ErrorCode
);
837 /* Initialize the Async Thread */
838 if (!WsAsyncCheckAndInitThread())
841 SetLastError(WSAENOBUFS
);
845 /* Allocate an async block */
846 if (!(AsyncBlock
= WsAsyncAllocateBlock(strlen(Name
) + sizeof(CHAR
))))
849 SetLastError(WSAENOBUFS
);
853 /* Make a copy of the address */
854 NameCopy
= AsyncBlock
+ 1;
855 strcpy(NameCopy
, Name
);
857 /* Initialize the Async Block */
858 AsyncBlock
->Operation
= WsAsyncGetProtoByName
;
859 AsyncBlock
->GetServ
.hWnd
= hWnd
;
860 AsyncBlock
->GetServ
.wMsg
= wMsg
;
861 AsyncBlock
->GetServ
.ByWhat
= NameCopy
;
862 AsyncBlock
->GetServ
.Protocol
= (PCHAR
)Protocol
;
863 AsyncBlock
->GetServ
.Buffer
= Buffer
;
864 AsyncBlock
->GetServ
.BufferLength
= BufferLength
;
866 /* Save the task handle and queue the request */
867 TaskHandle
= AsyncBlock
->TaskHandle
;
868 WsAsyncQueueRequest(AsyncBlock
);
870 /* Return the task handle */
879 WSAAsyncGetServByPort(IN HWND hWnd
,
882 IN CONST CHAR FAR
*Protocol
,
883 OUT CHAR FAR
*Buffer
,
889 PWSASYNCBLOCK AsyncBlock
;
891 DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd
, wMsg
, Port
);
894 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
897 SetLastError(ErrorCode
);
901 /* Initialize the Async Thread */
902 if (!WsAsyncCheckAndInitThread())
905 SetLastError(WSAENOBUFS
);
909 /* Allocate an async block */
910 if (!(AsyncBlock
= WsAsyncAllocateBlock(0)))
913 SetLastError(WSAENOBUFS
);
917 /* Initialize the Async Block */
918 AsyncBlock
->Operation
= WsAsyncGetServByPort
;
919 AsyncBlock
->GetServ
.hWnd
= hWnd
;
920 AsyncBlock
->GetServ
.wMsg
= wMsg
;
921 AsyncBlock
->GetServ
.ByWhat
= UlongToPtr(Port
);
922 AsyncBlock
->GetServ
.Protocol
= (PCHAR
)Protocol
;
923 AsyncBlock
->GetServ
.Buffer
= Buffer
;
924 AsyncBlock
->GetServ
.BufferLength
= BufferLength
;
926 /* Save the task handle and queue the request */
927 TaskHandle
= AsyncBlock
->TaskHandle
;
928 WsAsyncQueueRequest(AsyncBlock
);
930 /* Return the task handle */
939 WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle
)
944 DPRINT("WSACancelAsyncRequest: %lx\n", hAsyncTaskHandle
);
947 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) == ERROR_SUCCESS
)
949 /* Call the Async code */
950 ErrorCode
= WsAsyncCancelRequest(hAsyncTaskHandle
);
953 if (ErrorCode
== ERROR_SUCCESS
) return ERROR_SUCCESS
;
957 SetLastError(ErrorCode
);