xref: /reactos/dll/win32/ws2_32/src/getxbyxx.c (revision 682f85ad)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32/src/getxbyxx.c
5  * PURPOSE:     Get X by Y Functions for Name Resolution.
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* DATA **********************************************************************/
17 
18 AFPROTOCOLS afp[2] = {{AF_INET, IPPROTO_UDP}, {AF_INET, IPPROTO_TCP}};
19 
20 /* FUNCTIONS *****************************************************************/
21 
22 VOID
23 WSAAPI
FixList(PCHAR ** List,ULONG_PTR Base)24 FixList(PCHAR **List,
25         ULONG_PTR Base)
26 {
27     /* Make sure it's valid */
28     if (*List)
29     {
30         PCHAR *Addr;
31 
32         /* Get the right base */
33         Addr = *List = (PCHAR*)(((ULONG_PTR)*List + Base));
34 
35         /* Loop the pointers */
36         while (*Addr)
37         {
38             /* Rebase them too */
39             *Addr = (PCHAR)(((ULONG_PTR)*Addr + Base));
40             Addr++;
41         }
42     }
43 }
44 
45 VOID
46 WSAAPI
UnpackServEnt(PSERVENT Servent)47 UnpackServEnt(PSERVENT Servent)
48 {
49     ULONG_PTR ServentPtr = (ULONG_PTR)Servent;
50 
51     /* Convert all the List Offsets to Pointers */
52     FixList(&Servent->s_aliases, ServentPtr);
53 
54     /* Convert the Name and Protocol Offsets to Pointers */
55     Servent->s_name = (PCHAR)(Servent->s_name + ServentPtr);
56     Servent->s_proto = (PCHAR)(Servent->s_proto + ServentPtr);
57 }
58 
59 VOID
60 WSAAPI
UnpackHostEnt(PHOSTENT Hostent)61 UnpackHostEnt(PHOSTENT Hostent)
62 {
63     ULONG_PTR HostentPtr = (ULONG_PTR)Hostent;
64 
65     /* Convert the Name Offset to a Pointer */
66     if (Hostent->h_name) Hostent->h_name = (PCHAR)(Hostent->h_name + HostentPtr);
67 
68     /* Convert all the List Offsets to Pointers */
69     FixList(&Hostent->h_aliases, HostentPtr);
70     FixList(&Hostent->h_addr_list, HostentPtr);
71 }
72 
73 VOID
74 WSAAPI
Local_Ip4AddresstoString(IN PCHAR AddressBuffer,IN PCHAR Address)75 Local_Ip4AddresstoString(IN PCHAR AddressBuffer,
76                          IN PCHAR Address)
77 {
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));
84 }
85 
86 VOID
87 WSAAPI
Local_Ip6AddresstoString(IN PCHAR AddressBuffer,IN PCHAR Address)88 Local_Ip6AddresstoString(IN PCHAR AddressBuffer,
89                          IN PCHAR Address)
90 {
91     DWORD i;
92 
93     /* Convert the address into IPv6 format */
94     for (i = 0; i < 8; i++)
95     {
96         sprintf(AddressBuffer, "%x:",
97                 ((unsigned)Address[0] & 0xff));
98     }
99 }
100 
101 LPBLOB
102 WSAAPI
getxyDataEnt(IN OUT PCHAR * Results,IN DWORD Length,IN LPSTR Name,IN LPCGUID Type,IN LPSTR * NewName)103 getxyDataEnt(IN OUT PCHAR *Results,
104              IN DWORD Length,
105              IN LPSTR Name,
106              IN LPCGUID Type,
107              IN LPSTR *NewName)
108 {
109     PWSAQUERYSETA WsaQuery = (PWSAQUERYSETA)*Results;
110     INT ErrorCode;
111     DWORD NewLength = Length;
112     HANDLE RnRHandle;
113     LPBLOB Blob = NULL;
114     PVOID NewResults = NULL;
115     DWORD dwControlFlags = LUP_RETURN_NAME;
116 
117     /* Assume empty return name */
118     if (NewName) *NewName = NULL;
119 
120     /* Set up the Winsock Service Query */
121     RtlZeroMemory(WsaQuery, sizeof(*WsaQuery));
122     WsaQuery->dwSize = sizeof(*WsaQuery);
123     WsaQuery->lpszServiceInstanceName = Name;
124     WsaQuery->lpServiceClassId = (LPGUID)Type;
125     WsaQuery->dwNameSpace = NS_ALL;
126     WsaQuery->dwNumberOfProtocols = sizeof(afp)/sizeof(afp[0]);
127     WsaQuery->lpafpProtocols = afp;
128 
129     if (!IsEqualGUID(Type, &HostnameGuid))
130         dwControlFlags |= LUP_RETURN_BLOB;
131 
132     /* Send the Query Request to find a Service */
133     ErrorCode = WSALookupServiceBeginA(WsaQuery,
134                                        dwControlFlags,
135                                        &RnRHandle);
136 
137     if (ErrorCode == ERROR_SUCCESS)
138     {
139         while (TRUE)
140         {
141             /* Service was found, send the real query */
142             ErrorCode = WSALookupServiceNextA(RnRHandle,
143                                               0,
144                                               &NewLength,
145                                               WsaQuery);
146 
147             /* Return the information requested */
148             if (ErrorCode == ERROR_SUCCESS)
149             {
150                 /* Get the Blob and check if we have one */
151                 Blob = WsaQuery->lpBlob;
152                 if (Blob)
153                 {
154                     /* Did they want the name back? */
155                     if (NewName) *NewName = WsaQuery->lpszServiceInstanceName;
156                 }
157                 else
158                 {
159                     /* Check if this was a Hostname lookup */
160                     if (IsEqualGUID(Type, &HostnameGuid))
161                     {
162                         /* Return the name anyways */
163                         if (NewName) *NewName = WsaQuery->lpszServiceInstanceName;
164                     }
165                     else
166                     {
167                         /* We don't have a blob, sorry */
168                         ErrorCode = WSANO_DATA;
169                     }
170                 }
171             }
172             else
173             {
174                 /* WSALookupServiceEnd will set its own error, so save ours */
175                 ErrorCode = GetLastError();
176 
177                 /* Check if we failed because of missing buffer space */
178                 if ((ErrorCode == WSAEFAULT) && (Length > RNR_BUFFER_SIZE))
179                 {
180                     /* Allocate a new buffer */
181                     NewResults = HeapAlloc(WsSockHeap, 0, Length);
182                     if (NewResults)
183                     {
184                         /* Tell the caller his new buffer */
185                         *Results = NewResults;
186 
187                         /* Update the WSA Query's location */
188                         WsaQuery = (PWSAQUERYSETA)NewResults;
189 
190                         /* Loop again */
191                         continue;
192                     }
193                     else
194                     {
195                         /* No memory to allocate the new buffer */
196                         ErrorCode = WSA_NOT_ENOUGH_MEMORY;
197                     }
198                 }
199             }
200 
201             /* Finish the Query Request */
202             WSALookupServiceEnd(RnRHandle);
203 
204             /* Now set the Last Error */
205             if (ErrorCode != ERROR_SUCCESS) SetLastError(ErrorCode);
206 
207             /* Leave the loop */
208             break;
209         }
210     }
211 
212     /* Return the blob */
213     return Blob;
214 }
215 
216 /*
217  * @implemented
218  */
219 PHOSTENT
220 WSAAPI
gethostbyname(IN const char FAR * name)221 gethostbyname(IN const char FAR * name)
222 {
223     PHOSTENT Hostent;
224     LPBLOB Blob;
225     INT ErrorCode;
226     CHAR ResultsBuffer[RNR_BUFFER_SIZE];
227     PCHAR Results = ResultsBuffer;
228     CHAR szLocalName[MAX_HOSTNAME_LEN];
229     PCHAR pszName;
230     PWSPROCESS Process;
231     PWSTHREAD Thread;
232     DPRINT("gethostbyname: %s\n", name);
233 
234     /* Enter prolog */
235     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
236     {
237         /* Leave now */
238         SetLastError(ErrorCode);
239         return NULL;
240     }
241 
242     /* Check if no name was given */
243     if (!name || !*name)
244     {
245         /* This means we should do a local lookup first */
246         if (gethostname(szLocalName, MAX_HOSTNAME_LEN) != NO_ERROR) return(NULL);
247         pszName = szLocalName;
248     }
249     else
250     {
251         /* Use the name tha twas given to us */
252         pszName = (PCHAR)name;
253     }
254 
255     /* Get the Hostname in a Blob Structure */
256     Blob = getxyDataEnt(&Results,
257                         RNR_BUFFER_SIZE,
258                         pszName,
259                         &HostAddrByNameGuid,
260                         0);
261 
262     /* Check if we didn't get a blob, or if we got an empty name */
263     if (!(Blob) && (!(name) || !(*name)))
264     {
265         /* Try a new query */
266         Blob = getxyDataEnt(&Results,
267                             RNR_BUFFER_SIZE,
268                             NULL,
269                             &HostAddrByNameGuid,
270                             0);
271     }
272 
273     /* Check if we got a blob */
274     if (Blob)
275     {
276         /* Copy the blob to our buffer and convert it */
277         Hostent = WsThreadBlobToHostent(Thread, Blob);
278 
279         /* Unpack the hostent */
280         if (Hostent) UnpackHostEnt(Hostent);
281     }
282     else
283     {
284         /* We failed, so zero it out */
285         Hostent = NULL;
286 
287         /* Normalize the error message */
288         if (GetLastError() == WSASERVICE_NOT_FOUND)
289         {
290             SetLastError(WSAHOST_NOT_FOUND);
291         }
292     }
293 
294     /* Check if we received a newly allocated buffer; free it. */
295     if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
296 
297     /* Notify RAS Auto-dial helper */
298     if (Hostent) WSNoteSuccessfulHostentLookup(name, *Hostent->h_addr);
299 
300     /* Return the hostent */
301     return Hostent;
302 }
303 
304 /*
305  * @implemented
306  */
307 PHOSTENT
308 WSAAPI
gethostbyaddr(IN const char FAR * addr,IN int len,IN int type)309 gethostbyaddr(IN const char FAR * addr,
310               IN int len,
311               IN int type)
312 {
313     CHAR AddressBuffer[100];
314     PHOSTENT Hostent;
315     LPBLOB Blob;
316     CHAR ResultsBuffer[RNR_BUFFER_SIZE];
317     PCHAR Results = ResultsBuffer;
318     PWSPROCESS Process;
319     PWSTHREAD Thread;
320     INT ErrorCode;
321     DPRINT("gethostbyaddr: %s\n", addr);
322 
323     /* Enter prolog */
324     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
325     {
326         /* Leave now */
327         SetLastError(ErrorCode);
328         return NULL;
329     }
330 
331     /* Check for valid address pointer */
332     if (!addr)
333     {
334         /* Fail */
335         SetLastError(WSAEINVAL);
336         return NULL;
337     }
338 
339     /* Check which type it is */
340     if (type == AF_INET)
341     {
342         /* Use IPV4 Address to String */
343         Local_Ip4AddresstoString(AddressBuffer, (PCHAR)addr);
344     }
345     else if (type == AF_INET6)
346     {
347         /* Use IPV6 Address to String */
348         Local_Ip6AddresstoString(AddressBuffer, (PCHAR)addr);
349     }
350     else
351     {
352         /* Invalid address type; fail */
353         SetLastError(WSAEINVAL);
354         return NULL;
355     }
356 
357     /* Get the Hostname in a Blob Structure */
358     Blob = getxyDataEnt(&Results,
359                         RNR_BUFFER_SIZE,
360                         AddressBuffer,
361                         &AddressGuid,
362                         0);
363 
364     /* Check if we got a blob */
365     if (Blob)
366     {
367         /* Copy the blob to our buffer and convert it */
368         Hostent = WsThreadBlobToHostent(Thread, Blob);
369 
370         /* Unpack the hostent */
371         if (Hostent) UnpackHostEnt(Hostent);
372     }
373     else
374     {
375         /* We failed, so zero it out */
376         Hostent = NULL;
377 
378         /* Normalize the error message */
379         if (GetLastError() == WSASERVICE_NOT_FOUND)
380         {
381             SetLastError(WSAHOST_NOT_FOUND);
382         }
383     }
384 
385     /* Check if we received a newly allocated buffer; free it. */
386     if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
387 
388     /* Return the hostent */
389     return Hostent;
390 }
391 
392 /*
393  * @implemented
394  */
395 INT
396 WSAAPI
gethostname(OUT char FAR * name,IN INT namelen)397 gethostname(OUT char FAR * name,
398             IN INT namelen)
399 {
400     PCHAR Name = NULL;
401     CHAR ResultsBuffer[RNR_BUFFER_SIZE];
402     PCHAR Results = ResultsBuffer;
403     DPRINT("gethostname: %p\n", name);
404 
405     if (!name || namelen < 1)
406     {
407         SetLastError(WSAEFAULT);
408         return SOCKET_ERROR;
409     }
410     /* Get the Hostname in a String */
411     /* getxyDataEnt does not return blob for HostnameGuid */
412     getxyDataEnt(&Results, RNR_BUFFER_SIZE, NULL, &HostnameGuid, &Name);
413     if (Name)
414     {
415         /* Copy it */
416         strncpy(name, Name, namelen-1);
417     }
418 
419     /* Check if we received a newly allocated buffer; free it. */
420     if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
421 
422     /* Return success */
423     return ERROR_SUCCESS;
424 }
425 
426 /*
427  * @implemented
428  */
429 PSERVENT
430 WSAAPI
getservbyport(IN int port,IN const char FAR * proto)431 getservbyport(IN int port,
432               IN const char FAR * proto)
433 {
434     PSERVENT Servent;
435     LPBLOB Blob;
436     CHAR ResultsBuffer[RNR_BUFFER_SIZE];
437     PCHAR Results = ResultsBuffer;
438     PCHAR PortName;
439     PWSPROCESS Process;
440     PWSTHREAD Thread;
441     INT ErrorCode;
442     DPRINT("getservbyport: %s\n", proto);
443 
444     /* Enter prolog */
445     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
446     {
447         /* Leave now */
448         SetLastError(ErrorCode);
449         return NULL;
450     }
451 
452     /* No protocol specified */
453     if (!proto) proto = "";
454 
455     /* Allocate memory for the port name */
456     PortName = HeapAlloc(WsSockHeap, 0, strlen(proto) + 1 + 1 + 5);
457     if (!PortName)
458     {
459         /* Fail */
460         SetLastError(WSA_NOT_ENOUGH_MEMORY);
461         return NULL;
462     }
463 
464     /* Put it into the right syntax */
465     sprintf(PortName, "%d/%s", (ntohs(port) & 0xffff), proto);
466 
467     /* Get the Service in a Blob */
468     Blob = getxyDataEnt(&Results, RNR_BUFFER_SIZE, PortName, &IANAGuid, 0);
469 
470     /* Free the string we sent */
471     HeapFree(WsSockHeap, 0, PortName);
472 
473     /* Check if we got a blob */
474     if (Blob)
475     {
476         /* Copy the blob to our buffer and convert it */
477         Servent = WsThreadBlobToServent(Thread, Blob);
478 
479         /* Unpack the hostent */
480         if (Servent) UnpackServEnt(Servent);
481     }
482     else
483     {
484         /* We failed, so zero it out */
485         Servent = 0;
486     }
487 
488     /* Check if we received a newly allocated buffer; free it. */
489     if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
490 
491     /* Return the hostent */
492     return Servent;
493 }
494 
495 /*
496  * @implemented
497  */
498 PSERVENT
499 WSAAPI
getservbyname(IN const char FAR * name,IN const char FAR * proto)500 getservbyname(IN const char FAR * name,
501               IN const char FAR * proto)
502 {
503     PSERVENT Servent;
504     LPBLOB Blob;
505     CHAR ResultsBuffer[RNR_BUFFER_SIZE];
506     PCHAR Results = ResultsBuffer;
507     PCHAR PortName;
508     PWSPROCESS Process;
509     PWSTHREAD Thread;
510     INT ErrorCode;
511     DPRINT("getservbyname: %s\n", name);
512 
513     /* Enter prolog */
514     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
515     {
516         /* Leave now */
517         SetLastError(ErrorCode);
518         return NULL;
519     }
520 
521     /* No protocol specified */
522     if (!proto) proto = "";
523 
524     /* Allocate buffer for it */
525     PortName = HeapAlloc(WsSockHeap, 0, strlen(proto) + 1 + strlen(name) + 1);
526     if (!PortName)
527     {
528         /* Fail */
529         SetLastError(WSA_NOT_ENOUGH_MEMORY);
530         return NULL;
531     }
532 
533     /* Put it into the right syntax */
534     sprintf(PortName, "%s/%s", name, proto);
535 
536     /* Get the Service in a Blob */
537     Blob = getxyDataEnt(&Results, RNR_BUFFER_SIZE, PortName, &IANAGuid, 0);
538 
539     /* Free the string we sent */
540     HeapFree(WsSockHeap, 0, PortName);
541 
542     /* Check if we got a blob */
543     if (Blob)
544     {
545         /* Copy the blob to our buffer and convert it */
546         Servent = WsThreadBlobToServent(Thread, Blob);
547 
548         /* Unpack the hostent */
549         if (Servent) UnpackServEnt(Servent);
550     }
551     else
552     {
553         /* We failed, so zero it out */
554         Servent = 0;
555     }
556 
557     /* Check if we received a newly allocated buffer; free it. */
558     if (Results != ResultsBuffer) HeapFree(WsSockHeap, 0, Results);
559 
560     /* Return the hostent */
561     return Servent;
562 }
563 
564 /*
565  * @implemented
566  */
567 HANDLE
568 WSAAPI
WSAAsyncGetHostByAddr(IN HWND hWnd,IN UINT wMsg,IN CONST CHAR FAR * Address,IN INT Length,IN INT Type,OUT CHAR FAR * Buffer,IN INT BufferLength)569 WSAAsyncGetHostByAddr(IN HWND hWnd,
570                       IN UINT wMsg,
571                       IN CONST CHAR FAR *Address,
572                       IN INT Length,
573                       IN INT Type,
574                       OUT CHAR FAR *Buffer,
575                       IN INT BufferLength)
576 {
577     HANDLE TaskHandle;
578     PWSPROCESS Process;
579     PWSTHREAD Thread;
580     PVOID AddressCopy;
581     PWSASYNCBLOCK AsyncBlock;
582     INT ErrorCode;
583     DPRINT("WSAAsyncGetHostByAddr: %lx, %lx, %s\n", hWnd, wMsg, Address);
584 
585     /* Enter prolog */
586     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
587     {
588         /* Leave now */
589         SetLastError(ErrorCode);
590         return NULL;
591     }
592 
593     /* Initialize the Async Thread */
594     if (!WsAsyncCheckAndInitThread())
595     {
596         /* Fail */
597         SetLastError(WSAENOBUFS);
598         return NULL;
599     }
600 
601     /* Allocate an async block */
602     if (!(AsyncBlock = WsAsyncAllocateBlock(Length)))
603     {
604         /* Fail */
605         SetLastError(WSAENOBUFS);
606         return NULL;
607     }
608 
609     /* Make a copy of the address */
610     AddressCopy = AsyncBlock + 1;
611     RtlMoveMemory(AddressCopy, Address, Length);
612 
613     /* Initialize the Async Block */
614     AsyncBlock->Operation = WsAsyncGetHostByAddr;
615     AsyncBlock->GetHost.hWnd = hWnd;
616     AsyncBlock->GetHost.wMsg = wMsg;
617     AsyncBlock->GetHost.ByWhat = AddressCopy;
618     AsyncBlock->GetHost.Length = Length;
619     AsyncBlock->GetHost.Type = Type;
620     AsyncBlock->GetHost.Buffer = Buffer;
621     AsyncBlock->GetHost.BufferLength = BufferLength;
622 
623     /* Save the task handle and queue the request */
624     TaskHandle = AsyncBlock->TaskHandle;
625     WsAsyncQueueRequest(AsyncBlock);
626 
627     /* Return the task handle */
628     return TaskHandle;
629 }
630 
631 /*
632  * @implemented
633  */
634 HANDLE
635 WSAAPI
WSAAsyncGetHostByName(IN HWND hWnd,IN UINT wMsg,IN CONST CHAR FAR * Name,OUT CHAR FAR * Buffer,IN INT BufferLength)636 WSAAsyncGetHostByName(IN HWND hWnd,
637                       IN UINT wMsg,
638                       IN CONST CHAR FAR *Name,
639                       OUT CHAR FAR *Buffer,
640                       IN INT BufferLength)
641 {
642     HANDLE TaskHandle;
643     PWSPROCESS Process;
644     PWSTHREAD Thread;
645     PWSASYNCBLOCK AsyncBlock;
646     INT ErrorCode;
647     PVOID NameCopy;
648     DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd, wMsg, Name);
649 
650     /* Enter prolog */
651     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
652     {
653         /* Leave now */
654         SetLastError(ErrorCode);
655         return NULL;
656     }
657 
658     /* Initialize the Async Thread */
659     if (!WsAsyncCheckAndInitThread())
660     {
661         /* Fail */
662         SetLastError(WSAENOBUFS);
663         return NULL;
664     }
665 
666     /* Allocate an async block */
667     if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
668     {
669         /* Fail */
670         SetLastError(WSAENOBUFS);
671         return NULL;
672     }
673 
674     /* Make a copy of the address */
675     NameCopy = AsyncBlock + 1;
676     strcpy(NameCopy, Name);
677 
678     /* Initialize the Async Block */
679     AsyncBlock->Operation = WsAsyncGetHostByName;
680     AsyncBlock->GetHost.hWnd = hWnd;
681     AsyncBlock->GetHost.wMsg = wMsg;
682     AsyncBlock->GetHost.ByWhat = NameCopy;
683     AsyncBlock->GetHost.Buffer = Buffer;
684     AsyncBlock->GetHost.BufferLength = BufferLength;
685 
686     /* Save the task handle and queue the request */
687     TaskHandle = AsyncBlock->TaskHandle;
688     WsAsyncQueueRequest(AsyncBlock);
689 
690     /* Return the task handle */
691     return TaskHandle;
692 }
693 
694 /*
695  * @implemented
696  */
697 HANDLE
698 WSAAPI
WSAAsyncGetProtoByName(IN HWND hWnd,IN UINT wMsg,IN CONST CHAR FAR * Name,OUT CHAR FAR * Buffer,IN INT BufferLength)699 WSAAsyncGetProtoByName(IN HWND hWnd,
700                        IN UINT wMsg,
701                        IN CONST CHAR FAR *Name,
702                        OUT CHAR FAR *Buffer,
703                        IN INT BufferLength)
704 {
705     HANDLE TaskHandle;
706     PWSPROCESS Process;
707     PWSTHREAD Thread;
708     PWSASYNCBLOCK AsyncBlock;
709     INT ErrorCode;
710     PVOID NameCopy;
711     DPRINT("WSAAsyncGetProtoByName: %lx, %lx, %s\n", hWnd, wMsg, Name);
712 
713     /* Enter prolog */
714     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
715     {
716         /* Leave now */
717         SetLastError(ErrorCode);
718         return NULL;
719     }
720 
721     /* Initialize the Async Thread */
722     if (!WsAsyncCheckAndInitThread())
723     {
724         /* Fail */
725         SetLastError(WSAENOBUFS);
726         return NULL;
727     }
728 
729     /* Allocate an async block */
730     if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
731     {
732         /* Fail */
733         SetLastError(WSAENOBUFS);
734         return NULL;
735     }
736 
737     /* Make a copy of the address */
738     NameCopy = AsyncBlock + 1;
739     strcpy(NameCopy, Name);
740 
741     /* Initialize the Async Block */
742     AsyncBlock->Operation = WsAsyncGetProtoByName;
743     AsyncBlock->GetProto.hWnd = hWnd;
744     AsyncBlock->GetProto.wMsg = wMsg;
745     AsyncBlock->GetProto.ByWhat = NameCopy;
746     AsyncBlock->GetProto.Buffer = Buffer;
747     AsyncBlock->GetProto.BufferLength = BufferLength;
748 
749     /* Save the task handle and queue the request */
750     TaskHandle = AsyncBlock->TaskHandle;
751     WsAsyncQueueRequest(AsyncBlock);
752 
753     /* Return the task handle */
754     return TaskHandle;
755 }
756 
757 /*
758  * @implemented
759  */
760 HANDLE
761 WSAAPI
WSAAsyncGetProtoByNumber(IN HWND hWnd,IN UINT wMsg,IN INT Number,OUT CHAR FAR * Buffer,IN INT BufferLength)762 WSAAsyncGetProtoByNumber(IN HWND hWnd,
763                          IN UINT wMsg,
764                          IN INT Number,
765                          OUT CHAR FAR* Buffer,
766                          IN INT BufferLength)
767 {
768     HANDLE TaskHandle;
769     PWSPROCESS Process;
770     PWSTHREAD Thread;
771     PWSASYNCBLOCK AsyncBlock;
772     INT ErrorCode;
773     DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd, wMsg, Number);
774 
775     /* Enter prolog */
776     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
777     {
778         /* Leave now */
779         SetLastError(ErrorCode);
780         return NULL;
781     }
782 
783     /* Initialize the Async Thread */
784     if (!WsAsyncCheckAndInitThread())
785     {
786         /* Fail */
787         SetLastError(WSAENOBUFS);
788         return NULL;
789     }
790 
791     /* Allocate an async block */
792     if (!(AsyncBlock = WsAsyncAllocateBlock(0)))
793     {
794         /* Fail */
795         SetLastError(WSAENOBUFS);
796         return NULL;
797     }
798 
799     /* Initialize the Async Block */
800     AsyncBlock->Operation = WsAsyncGetProtoByNumber;
801     AsyncBlock->GetProto.hWnd = hWnd;
802     AsyncBlock->GetProto.wMsg = wMsg;
803     AsyncBlock->GetProto.ByWhat = UlongToPtr(Number);
804     AsyncBlock->GetProto.Buffer = Buffer;
805     AsyncBlock->GetProto.BufferLength = BufferLength;
806 
807     /* Save the task handle and queue the request */
808     TaskHandle = AsyncBlock->TaskHandle;
809     WsAsyncQueueRequest(AsyncBlock);
810 
811     /* Return the task handle */
812     return TaskHandle;
813 }
814 
815 /*
816  * @implemented
817  */
818 HANDLE
819 WSAAPI
WSAAsyncGetServByName(IN HWND hWnd,IN UINT wMsg,IN CONST CHAR FAR * Name,IN CONST CHAR FAR * Protocol,OUT CHAR FAR * Buffer,IN INT BufferLength)820 WSAAsyncGetServByName(IN HWND hWnd,
821                       IN UINT wMsg,
822                       IN CONST CHAR FAR *Name,
823                       IN CONST CHAR FAR *Protocol,
824                       OUT CHAR FAR *Buffer,
825                       IN INT BufferLength)
826 {
827     HANDLE TaskHandle;
828     PWSPROCESS Process;
829     PWSTHREAD Thread;
830     PWSASYNCBLOCK AsyncBlock;
831     INT ErrorCode;
832     PVOID NameCopy;
833     DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %s\n", hWnd, wMsg, Name);
834 
835     /* Enter prolog */
836     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
837     {
838         /* Leave now */
839         SetLastError(ErrorCode);
840         return NULL;
841     }
842 
843     /* Initialize the Async Thread */
844     if (!WsAsyncCheckAndInitThread())
845     {
846         /* Fail */
847         SetLastError(WSAENOBUFS);
848         return NULL;
849     }
850 
851     /* Allocate an async block */
852     if (!(AsyncBlock = WsAsyncAllocateBlock(strlen(Name) + sizeof(CHAR))))
853     {
854         /* Fail */
855         SetLastError(WSAENOBUFS);
856         return NULL;
857     }
858 
859     /* Make a copy of the address */
860     NameCopy = AsyncBlock + 1;
861     strcpy(NameCopy, Name);
862 
863     /* Initialize the Async Block */
864     AsyncBlock->Operation = WsAsyncGetProtoByName;
865     AsyncBlock->GetServ.hWnd = hWnd;
866     AsyncBlock->GetServ.wMsg = wMsg;
867     AsyncBlock->GetServ.ByWhat = NameCopy;
868     AsyncBlock->GetServ.Protocol = (PCHAR)Protocol;
869     AsyncBlock->GetServ.Buffer = Buffer;
870     AsyncBlock->GetServ.BufferLength = BufferLength;
871 
872     /* Save the task handle and queue the request */
873     TaskHandle = AsyncBlock->TaskHandle;
874     WsAsyncQueueRequest(AsyncBlock);
875 
876     /* Return the task handle */
877     return TaskHandle;
878 }
879 
880 /*
881  * @implemented
882  */
883 HANDLE
884 WSAAPI
WSAAsyncGetServByPort(IN HWND hWnd,IN UINT wMsg,IN INT Port,IN CONST CHAR FAR * Protocol,OUT CHAR FAR * Buffer,IN INT BufferLength)885 WSAAsyncGetServByPort(IN HWND hWnd,
886                       IN UINT wMsg,
887                       IN INT Port,
888                       IN CONST CHAR FAR *Protocol,
889                       OUT CHAR FAR *Buffer,
890                       IN INT BufferLength)
891 {
892     HANDLE TaskHandle;
893     PWSPROCESS Process;
894     PWSTHREAD Thread;
895     PWSASYNCBLOCK AsyncBlock;
896     INT ErrorCode;
897     DPRINT("WSAAsyncGetProtoByNumber: %lx, %lx, %lx\n", hWnd, wMsg, Port);
898 
899     /* Enter prolog */
900     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
901     {
902         /* Leave now */
903         SetLastError(ErrorCode);
904         return NULL;
905     }
906 
907     /* Initialize the Async Thread */
908     if (!WsAsyncCheckAndInitThread())
909     {
910         /* Fail */
911         SetLastError(WSAENOBUFS);
912         return NULL;
913     }
914 
915     /* Allocate an async block */
916     if (!(AsyncBlock = WsAsyncAllocateBlock(0)))
917     {
918         /* Fail */
919         SetLastError(WSAENOBUFS);
920         return NULL;
921     }
922 
923     /* Initialize the Async Block */
924     AsyncBlock->Operation = WsAsyncGetServByPort;
925     AsyncBlock->GetServ.hWnd = hWnd;
926     AsyncBlock->GetServ.wMsg = wMsg;
927     AsyncBlock->GetServ.ByWhat = UlongToPtr(Port);
928     AsyncBlock->GetServ.Protocol = (PCHAR)Protocol;
929     AsyncBlock->GetServ.Buffer = Buffer;
930     AsyncBlock->GetServ.BufferLength = BufferLength;
931 
932     /* Save the task handle and queue the request */
933     TaskHandle = AsyncBlock->TaskHandle;
934     WsAsyncQueueRequest(AsyncBlock);
935 
936     /* Return the task handle */
937     return TaskHandle;
938 }
939 
940 /*
941  * @implemented
942  */
943 INT
944 WSAAPI
WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle)945 WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle)
946 {
947     PWSPROCESS Process;
948     PWSTHREAD Thread;
949     INT ErrorCode;
950     DPRINT("WSACancelAsyncRequest: %lx\n", hAsyncTaskHandle);
951 
952     /* Enter prolog */
953     if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
954     {
955         /* Call the Async code */
956         ErrorCode = WsAsyncCancelRequest(hAsyncTaskHandle);
957 
958         /* Return */
959         if (ErrorCode == ERROR_SUCCESS) return ERROR_SUCCESS;
960     }
961 
962     /* Fail */
963     SetLastError(ErrorCode);
964     return SOCKET_ERROR;
965 }
966