xref: /reactos/dll/win32/ws2_32/src/rnr.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/rnr.c
5  * PURPOSE:     Registration and Resolution Support
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 /* FUNCTIONS *****************************************************************/
17 
18 /*
19  * @implemented
20  */
21 INT
22 WSAAPI
WSAAddressToStringA(IN LPSOCKADDR lpsaAddress,IN DWORD dwAddressLength,IN LPWSAPROTOCOL_INFOA lpProtocolInfo,OUT LPSTR lpszAddressString,IN OUT LPDWORD lpdwAddressStringLength)23 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress,
24                     IN DWORD dwAddressLength,
25                     IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
26                     OUT LPSTR lpszAddressString,
27                     IN OUT  LPDWORD lpdwAddressStringLength)
28 {
29     PWSPROCESS Process;
30     PWSTHREAD Thread;
31     INT ErrorCode, Status;
32     DWORD CatalogEntryId;
33     PTCATALOG Catalog;
34     PTCATALOG_ENTRY CatalogEntry;
35     LPWSTR UnicodeString;
36     DWORD Length = *lpdwAddressStringLength;
37 
38     DPRINT("WSAAddressToStringA: %p\n", lpsaAddress);
39 
40     /* Enter prolog */
41     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
42     {
43         /* Leave now */
44         SetLastError(ErrorCode);
45         return SOCKET_ERROR;
46     }
47 
48     /* Allocate the unicode string */
49     UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2);
50     if (!UnicodeString)
51     {
52         /* No memory; fail */
53         SetLastError(WSAENOBUFS);
54         return SOCKET_ERROR;
55     }
56 
57     /* Get the catalog */
58     Catalog = WsProcGetTCatalog(Process);
59 
60     /* Check if we got custom protocol info */
61     if (lpProtocolInfo)
62     {
63         /* Get the entry ID */
64         CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
65 
66         /* Get the entry associated with it */
67         ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
68                                                    CatalogEntryId,
69                                                    &CatalogEntry);
70     }
71     else
72     {
73         /* Get it from the address family */
74         ErrorCode = WsTcGetEntryFromAf(Catalog,
75                                        lpsaAddress->sa_family,
76                                        &CatalogEntry);
77     }
78 
79     /* Check for success */
80     if (ErrorCode == ERROR_SUCCESS)
81     {
82         /* Call the provider */
83         Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress,
84                                                                       dwAddressLength,
85                                                                       &CatalogEntry->
86                                                                       ProtocolInfo,
87                                                                       UnicodeString,
88                                                                       lpdwAddressStringLength,
89                                                                       &ErrorCode);
90         if (Status == ERROR_SUCCESS)
91         {
92             /* Convert the string */
93             WideCharToMultiByte(CP_ACP,
94                                 0,
95                                 UnicodeString,
96                                 -1,
97                                 lpszAddressString,
98                                 Length,
99                                 NULL,
100                                 NULL);
101         }
102 
103         /* Dereference the entry */
104         WsTcEntryDereference(CatalogEntry);
105 
106         /* Free the unicode string */
107         HeapFree(WsSockHeap, 0, UnicodeString);
108 
109         /* Check for success and return */
110         if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
111     }
112     else
113     {
114         /* Free the unicode string */
115         HeapFree(WsSockHeap, 0, UnicodeString);
116     }
117 
118     /* Set the error and return */
119     SetLastError(ErrorCode);
120     return SOCKET_ERROR;
121 }
122 
123 /*
124  * @implemented
125  */
126 INT
127 WSAAPI
WSAAddressToStringW(IN LPSOCKADDR lpsaAddress,IN DWORD dwAddressLength,IN LPWSAPROTOCOL_INFOW lpProtocolInfo,OUT LPWSTR lpszAddressString,IN OUT LPDWORD lpdwAddressStringLength)128 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress,
129                     IN DWORD dwAddressLength,
130                     IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
131                     OUT LPWSTR lpszAddressString,
132                     IN OUT LPDWORD lpdwAddressStringLength)
133 {
134     PWSPROCESS Process;
135     PWSTHREAD Thread;
136     INT ErrorCode, Status;
137     DWORD CatalogEntryId;
138     PTCATALOG Catalog;
139     PTCATALOG_ENTRY CatalogEntry;
140 
141     DPRINT("WSAAddressToStringW: %p\n", lpsaAddress);
142 
143     /* Enter prolog */
144     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
145     {
146         /* Leave now */
147         SetLastError(ErrorCode);
148         return SOCKET_ERROR;
149     }
150 
151     /* Get the catalog */
152     Catalog = WsProcGetTCatalog(Process);
153 
154     /* Check if we got custom protocol info */
155     if (lpProtocolInfo)
156     {
157         /* Get the entry ID */
158         CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
159 
160         /* Get the entry associated with it */
161         ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
162                                                    CatalogEntryId,
163                                                    &CatalogEntry);
164     }
165     else
166     {
167         /* Get it from the address family */
168         ErrorCode = WsTcGetEntryFromAf(Catalog,
169                                        lpsaAddress->sa_family,
170                                        &CatalogEntry);
171     }
172 
173     /* Check for success */
174     if (ErrorCode == ERROR_SUCCESS)
175     {
176         /* Call the provider */
177         Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress,
178                                                                       dwAddressLength,
179                                                                       &CatalogEntry->
180                                                                       ProtocolInfo,
181                                                                       lpszAddressString,
182                                                                       lpdwAddressStringLength,
183                                                                       &ErrorCode);
184 
185         /* Dereference the entry */
186         WsTcEntryDereference(CatalogEntry);
187 
188         /* Check for success and return */
189         if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
190     }
191 
192     /* Set the error and return */
193     SetLastError(ErrorCode);
194     return SOCKET_ERROR;
195 }
196 
197 /*
198  * @implemented
199  */
200 INT
201 WSAAPI
WSALookupServiceEnd(IN HANDLE hLookup)202 WSALookupServiceEnd(IN HANDLE hLookup)
203 {
204     PWSPROCESS Process;
205     PWSTHREAD Thread;
206     INT ErrorCode;
207     PNSQUERY Query = hLookup;
208 
209     DPRINT("WSALookupServiceEnd: %lx\n", hLookup);
210 
211     /* Enter prolog */
212     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
213     {
214         /* Leave now */
215         SetLastError(ErrorCode);
216         return SOCKET_ERROR;
217     }
218 
219     /* Check for a valid handle, then validate and reference it */
220     if (IsBadReadPtr(Query, sizeof(*Query)) || !WsNqValidateAndReference(Query))
221     {
222         /* Fail */
223         SetLastError(WSA_INVALID_HANDLE);
224         return SOCKET_ERROR;
225     }
226 
227     /* Do the lookup */
228     ErrorCode = WsNqLookupServiceEnd(Query);
229 
230     /* Remove the validation reference */
231     WsNqDereference(Query);
232 
233     /* Remove the keep-alive */
234     WsNqDereference(Query);
235 
236     /* Return */
237     return ERROR_SUCCESS;
238 }
239 
240 /*
241  * @implemented
242  */
243 INT
244 WSAAPI
WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions,IN DWORD dwControlFlags,OUT LPHANDLE lphLookup)245 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions,
246                        IN DWORD dwControlFlags,
247                        OUT LPHANDLE lphLookup)
248 {
249     INT ErrorCode;
250     LPWSAQUERYSETW UnicodeQuerySet = NULL;
251     SIZE_T UnicodeQuerySetSize = 0;
252 
253     DPRINT("WSALookupServiceBeginA: %p\n", lpqsRestrictions);
254 
255     /* Verify pointer */
256     if (IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)) ||
257         IsBadReadPtr(lpqsRestrictions->lpServiceClassId, sizeof(*lpqsRestrictions->lpServiceClassId)))
258     {
259         /* Invalid */
260         SetLastError(WSAEFAULT);
261         return SOCKET_ERROR;
262     }
263 
264     /* Clear the reserved fields */
265     lpqsRestrictions->dwOutputFlags = 0;
266     lpqsRestrictions->lpszComment = NULL;
267     lpqsRestrictions->dwNumberOfCsAddrs = 0;
268 
269     /* Find out the side we'll need */
270     ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions,
271                                          &UnicodeQuerySetSize,
272                                          UnicodeQuerySet);
273 
274     /* We should've failed */
275     if (ErrorCode == WSAEFAULT)
276     {
277         /* Allocate the buffer we'll need */
278         UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize);
279         if (UnicodeQuerySet)
280         {
281             /* Do the conversion for real */
282             ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions,
283                                                  &UnicodeQuerySetSize,
284                                                  UnicodeQuerySet);
285             if (ErrorCode == ERROR_SUCCESS)
286             {
287                 /* Now call the Unicode function */
288                 ErrorCode = WSALookupServiceBeginW(UnicodeQuerySet,
289                                                    dwControlFlags,
290                                                    lphLookup);
291             }
292 
293             /* Free our buffer */
294             HeapFree(WsSockHeap, 0, UnicodeQuerySet);
295         }
296         else
297         {
298             /* No memory to allocate */
299             ErrorCode = WSAEFAULT;
300         }
301     }
302 
303     /* Set the error in case of failure */
304     if (ErrorCode != ERROR_SUCCESS)
305         SetLastError(ErrorCode);
306 
307     /* Return to caller */
308     return ErrorCode == ERROR_SUCCESS ? ErrorCode : SOCKET_ERROR;
309 }
310 
311 /*
312  * @implemented
313  */
314 INT
315 WINAPI
WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions,IN DWORD dwControlFlags,OUT LPHANDLE lphLookup)316 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions,
317                        IN DWORD dwControlFlags,
318                        OUT LPHANDLE lphLookup)
319 {
320     PWSPROCESS Process;
321     PWSTHREAD Thread;
322     INT ErrorCode;
323     PNSQUERY Query;
324 
325     DPRINT("WSALookupServiceBeginW: %p\n", lpqsRestrictions);
326 
327     /* Enter prolog */
328     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
329     {
330         /* Leave now */
331         SetLastError(ErrorCode);
332         return SOCKET_ERROR;
333     }
334 
335     /* Verify pointers */
336     if (IsBadWritePtr(lphLookup, sizeof(*lphLookup)) ||
337         IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)) ||
338         IsBadReadPtr(lpqsRestrictions->lpServiceClassId, sizeof(*lpqsRestrictions->lpServiceClassId)))
339     {
340         /* They are invalid; fail */
341         SetLastError(WSAEFAULT);
342         return SOCKET_ERROR;
343     }
344 
345     /* Create a new query object */
346     if ((Query = WsNqAllocate()))
347     {
348         /* Initialize it */
349         WsNqInitialize(Query);
350 
351         /* Do the lookup */
352         ErrorCode = WsNqLookupServiceBegin(Query,
353                                            lpqsRestrictions,
354                                            dwControlFlags,
355                                            WsProcGetNsCatalog(Process));
356 
357         /* Check for success */
358         if (ErrorCode == ERROR_SUCCESS)
359         {
360             /* Return the handle */
361             *lphLookup = Query;
362         }
363         else
364         {
365             /* Fail */
366             *lphLookup = NULL;
367             WsNqDelete(Query);
368         }
369     }
370     else
371     {
372         /* No memory */
373         ErrorCode = SOCKET_ERROR;
374         SetLastError(WSAENOBUFS);
375     }
376 
377     /* Return */
378     return ErrorCode;
379 }
380 
381 /*
382  * @implemented
383  */
384 INT
385 WINAPI
WSALookupServiceNextW(IN HANDLE hLookup,IN DWORD dwControlFlags,IN OUT LPDWORD lpdwBufferLength,OUT LPWSAQUERYSETW lpqsResults)386 WSALookupServiceNextW(IN HANDLE hLookup,
387                       IN DWORD dwControlFlags,
388                       IN OUT LPDWORD lpdwBufferLength,
389                       OUT LPWSAQUERYSETW lpqsResults)
390 {
391     PWSPROCESS Process;
392     PWSTHREAD Thread;
393     INT ErrorCode;
394     PNSQUERY Query = hLookup;
395 
396     DPRINT("WSALookupServiceNextW: %lx\n", hLookup);
397 
398     /* Enter prolog */
399     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
400     {
401         /* Leave now */
402         SetLastError(ErrorCode);
403         return SOCKET_ERROR;
404     }
405 
406     /*
407      * Verify pointers. Note that the size of the buffer
408      * pointed by lpqsResults is given by *lpdwBufferLength.
409      */
410     if (IsBadReadPtr(lpdwBufferLength, sizeof(*lpdwBufferLength)) ||
411         IsBadWritePtr(lpqsResults, *lpdwBufferLength))
412     {
413         /* It is invalid; fail */
414         SetLastError(WSAEFAULT);
415         return SOCKET_ERROR;
416     }
417 
418     /* Check for a valid handle, then validate and reference it */
419     if (IsBadReadPtr(Query, sizeof(*Query)) || !WsNqValidateAndReference(Query))
420     {
421         /* Fail */
422         SetLastError(WSA_INVALID_HANDLE);
423         return SOCKET_ERROR;
424     }
425 
426     /* Do the lookup */
427     ErrorCode = WsNqLookupServiceNext(Query,
428                                       dwControlFlags,
429                                       lpdwBufferLength,
430                                       lpqsResults);
431 
432     /* Remove the validation reference */
433     WsNqDereference(Query);
434 
435     /* Return */
436     return ErrorCode;
437 }
438 
439 /*
440  * @implemented
441  */
442 INT
443 WSAAPI
WSALookupServiceNextA(IN HANDLE hLookup,IN DWORD dwControlFlags,IN OUT LPDWORD lpdwBufferLength,OUT LPWSAQUERYSETA lpqsResults)444 WSALookupServiceNextA(IN HANDLE hLookup,
445                       IN DWORD dwControlFlags,
446                       IN OUT LPDWORD lpdwBufferLength,
447                       OUT LPWSAQUERYSETA lpqsResults)
448 {
449     LPWSAQUERYSETW UnicodeQuerySet;
450     DWORD UnicodeQuerySetSize;
451     INT ErrorCode;
452 
453     DPRINT("WSALookupServiceNextA: %lx\n", hLookup);
454 
455     /*
456      * Verify pointers. Note that the size of the buffer
457      * pointed by lpqsResults is given by *lpdwBufferLength.
458      */
459     if (IsBadReadPtr(lpdwBufferLength, sizeof(*lpdwBufferLength)) ||
460         IsBadWritePtr(lpqsResults, *lpdwBufferLength))
461     {
462         /* It is invalid; fail */
463         SetLastError(WSAEFAULT);
464         return SOCKET_ERROR;
465     }
466 
467     UnicodeQuerySetSize = *lpdwBufferLength;
468 
469     /* Check how much the user is giving */
470     if (UnicodeQuerySetSize >= sizeof(WSAQUERYSETW))
471     {
472         /* Allocate the buffer we'll use */
473         UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize);
474         if (!UnicodeQuerySet)
475         {
476             /*
477              * We failed, possibly because the specified size was too large?
478              * Retrieve the needed buffer size with the WSALookupServiceNextW
479              * call and retry again a second time.
480              */
481             UnicodeQuerySetSize = 0;
482         }
483     }
484     else
485     {
486         /*
487          * The buffer is too small. Retrieve the needed buffer size with
488          * the WSALookupServiceNextW call and return it to the caller.
489          */
490         UnicodeQuerySet = NULL;
491         UnicodeQuerySetSize = 0;
492     }
493 
494     /* Call the Unicode Function */
495     ErrorCode = WSALookupServiceNextW(hLookup,
496                                       dwControlFlags,
497                                       &UnicodeQuerySetSize,
498                                       UnicodeQuerySet);
499 
500     /*
501      * Check whether we actually just retrieved the needed buffer size
502      * because our previous local allocation did fail. If so, allocate
503      * a new buffer and retry again.
504      */
505     if ( (!UnicodeQuerySet) && (*lpdwBufferLength >= sizeof(WSAQUERYSETW)) &&
506          (ErrorCode == SOCKET_ERROR) && (GetLastError() == WSAEFAULT) )
507     {
508         /* Allocate the buffer we'll use */
509         UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize);
510         if (UnicodeQuerySet)
511         {
512             /* Call the Unicode Function */
513             ErrorCode = WSALookupServiceNextW(hLookup,
514                                               dwControlFlags,
515                                               &UnicodeQuerySetSize,
516                                               UnicodeQuerySet);
517         }
518         /*
519          * Otherwise the allocation failed and we
520          * fall back into the error checks below.
521          */
522     }
523 
524     if (ErrorCode == ERROR_SUCCESS)
525     {
526         SIZE_T SetSize = *lpdwBufferLength;
527 
528         /* Now convert back to ANSI */
529         ErrorCode = MapUnicodeQuerySetToAnsi(UnicodeQuerySet,
530                                              &SetSize,
531                                              lpqsResults);
532         if (ErrorCode != ERROR_SUCCESS)
533         {
534             SetLastError(ErrorCode);
535         }
536         else if (SetSize > MAXDWORD)
537         {
538             ErrorCode = ERROR_ARITHMETIC_OVERFLOW;
539             SetLastError(ErrorCode);
540         }
541         else
542         {
543             *lpdwBufferLength = SetSize;
544         }
545     }
546     else
547     {
548         /* Check if we ran out of space */
549         if (GetLastError() == WSAEFAULT)
550         {
551             /* Return how much space we'll need, including padding */
552             *lpdwBufferLength = UnicodeQuerySetSize +
553                                 ((sizeof(ULONG) * 6) - (6 * 1));
554         }
555     }
556 
557     /* If we had a local buffer, free it */
558     if (UnicodeQuerySet)
559         HeapFree(WsSockHeap, 0, UnicodeQuerySet);
560 
561     /* Return to caller */
562     return (ErrorCode == ERROR_SUCCESS) ? ErrorCode : SOCKET_ERROR;
563 }
564 
565 /*
566  * @unimplemented
567  */
568 INT
569 WSPAPI
WSANSPIoctl(HANDLE hLookup,DWORD dwControlCode,LPVOID lpvInBuffer,DWORD cbInBuffer,LPVOID lpvOutBuffer,DWORD cbOutBuffer,LPDWORD lpcbBytesReturned,LPWSACOMPLETION lpCompletion)570 WSANSPIoctl(HANDLE hLookup,
571             DWORD dwControlCode,
572             LPVOID lpvInBuffer,
573             DWORD cbInBuffer,
574             LPVOID lpvOutBuffer,
575             DWORD cbOutBuffer,
576             LPDWORD lpcbBytesReturned,
577             LPWSACOMPLETION lpCompletion)
578 {
579     DPRINT("WSANSPIoctl: %lx\n", hLookup);
580     return 0;
581 }
582 
583 /*
584  * @unimplemented
585  */
586 INT
587 WSAAPI
WSARemoveServiceClass(IN LPGUID lpServiceClassId)588 WSARemoveServiceClass(IN LPGUID lpServiceClassId)
589 {
590     DPRINT("WSARemoveServiceClass: %lx\n", lpServiceClassId);
591     SetLastError(WSAEINVAL);
592     return SOCKET_ERROR;
593 }
594 
595 /*
596  * @unimplemented
597  */
598 INT
599 WSAAPI
WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo,IN WSAESETSERVICEOP essOperation,IN DWORD dwControlFlags)600 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo,
601                IN WSAESETSERVICEOP essOperation,
602                IN DWORD dwControlFlags)
603 {
604     DPRINT("WSASetServiceA: %lx\n", lpqsRegInfo);
605     SetLastError(WSAEINVAL);
606     return SOCKET_ERROR;
607 }
608 
609 /*
610  * @unimplemented
611  */
612 INT
613 WSAAPI
WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo,IN WSAESETSERVICEOP essOperation,IN DWORD dwControlFlags)614 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo,
615                IN WSAESETSERVICEOP essOperation,
616                IN DWORD dwControlFlags)
617 {
618     DPRINT("WSASetServiceW: %lx\n", lpqsRegInfo);
619     SetLastError(WSAEINVAL);
620     return SOCKET_ERROR;
621 }
622 
623 /*
624  * @unimplemented
625  */
626 INT
627 WSAAPI
WSAGetServiceClassInfoA(IN LPGUID lpProviderId,IN LPGUID lpServiceClassId,IN OUT LPDWORD lpdwBufferLength,OUT LPWSASERVICECLASSINFOA lpServiceClassInfo)628 WSAGetServiceClassInfoA(IN LPGUID lpProviderId,
629                         IN LPGUID lpServiceClassId,
630                         IN OUT LPDWORD lpdwBufferLength,
631                         OUT LPWSASERVICECLASSINFOA lpServiceClassInfo)
632 {
633     DPRINT("WSAGetServiceClassInfoA: %lx\n", lpProviderId);
634     SetLastError(WSAEINVAL);
635     return SOCKET_ERROR;
636 }
637 
638 /*
639  * @unimplemented
640  */
641 INT
642 WSAAPI
WSAGetServiceClassInfoW(IN LPGUID lpProviderId,IN LPGUID lpServiceClassId,IN OUT LPDWORD lpdwBufferLength,OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)643 WSAGetServiceClassInfoW(IN LPGUID lpProviderId,
644                         IN LPGUID lpServiceClassId,
645                         IN OUT LPDWORD lpdwBufferLength,
646                         OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
647 {
648     DPRINT("WSAGetServiceClassInfoW: %lx\n", lpProviderId);
649     SetLastError(WSAEINVAL);
650     return SOCKET_ERROR;
651 }
652 
653 /*
654  * @unimplemented
655  */
656 INT
657 WSAAPI
WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId,OUT LPSTR lpszServiceClassName,IN OUT LPDWORD lpdwBufferLength)658 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId,
659                                  OUT LPSTR lpszServiceClassName,
660                                  IN OUT LPDWORD lpdwBufferLength)
661 {
662     DPRINT("WSAGetServiceClassNameByClassIdA: %lx\n", lpServiceClassId);
663     SetLastError(WSAEINVAL);
664     return SOCKET_ERROR;
665 }
666 
667 /*
668  * @unimplemented
669  */
670 INT
671 WSAAPI
WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId,OUT LPWSTR lpszServiceClassName,IN OUT LPDWORD lpdwBufferLength)672 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId,
673                                  OUT LPWSTR lpszServiceClassName,
674                                  IN OUT LPDWORD lpdwBufferLength)
675 {
676     DPRINT("WSAGetServiceClassNameByClassIdW: %lx\n", lpServiceClassId);
677     SetLastError(WSAEINVAL);
678     return SOCKET_ERROR;
679 }
680 
681 /*
682  * @unimplemented
683  */
684 INT
685 WSAAPI
WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo)686 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo)
687 {
688     DPRINT("WSAInstallServiceClassA: %lx\n", lpServiceClassInfo);
689     SetLastError(WSAEINVAL);
690     return SOCKET_ERROR;
691 }
692 
693 /*
694 * @unimplemented
695 */
696 INT
697 WSAAPI
WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo)698 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo)
699 {
700     DPRINT("WSAInstallServiceClassW: %lx\n", lpServiceClassInfo);
701     SetLastError(WSAEINVAL);
702     return SOCKET_ERROR;
703 }
704 
705 VOID
706 WSAAPI
NSProviderInfoFromContext(IN PNSCATALOG_ENTRY Entry,IN PNSPROVIDER_ENUM_CONTEXT Context)707 NSProviderInfoFromContext(IN PNSCATALOG_ENTRY Entry,
708     IN PNSPROVIDER_ENUM_CONTEXT Context)
709 {
710     INT size = Context->Unicode ? sizeof(WSANAMESPACE_INFOW) : sizeof(WSANAMESPACE_INFOA);
711     /* Calculate ProviderName string size */
712     INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0;
713     INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR);
714     WSANAMESPACE_INFOW infoW;
715     /* Fill NS Provider data */
716     infoW.dwNameSpace = Entry->NamespaceId;
717     infoW.dwVersion = Entry->Version;
718     infoW.fActive = Entry->Enabled;
719     RtlMoveMemory(&infoW.NSProviderId,
720         &Entry->ProviderId,
721         sizeof(infoW.NSProviderId));
722     if (size2)
723     {
724         /* Calculate ProviderName string pointer */
725         infoW.lpszIdentifier = (LPWSTR)((ULONG_PTR)Context->ProtocolBuffer +
726             Context->BufferUsed + size);
727     }
728     else
729     {
730         infoW.lpszIdentifier = NULL;
731     }
732 
733     /* Check if we'll have space */
734     if ((Context->BufferUsed + size + size2) <=
735         (Context->BufferLength))
736     {
737         /* Copy the data */
738         RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer +
739             Context->BufferUsed),
740             &infoW,
741             size);
742         if (size2)
743         {
744             /* Entry->ProviderName is LPWSTR */
745             if (Context->Unicode)
746             {
747                 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer +
748                     Context->BufferUsed + size),
749                     Entry->ProviderName,
750                     size2);
751             }
752             else
753             {
754                 /* Call the conversion function */
755                 WideCharToMultiByte(CP_ACP,
756                     0,
757                     Entry->ProviderName,
758                     -1,
759                     (LPSTR)((ULONG_PTR)Context->ProtocolBuffer +
760                         Context->BufferUsed + size),
761                     size2,
762                     NULL,
763                     NULL);
764 
765             }
766         }
767 
768         /* Increase the count */
769         Context->Count++;
770     }
771 }
772 
773 BOOL
774 WSAAPI
NSProvidersEnumerationProc(PVOID EnumContext,PNSCATALOG_ENTRY Entry)775 NSProvidersEnumerationProc(PVOID EnumContext,
776     PNSCATALOG_ENTRY Entry)
777 {
778     PNSPROVIDER_ENUM_CONTEXT Context = (PNSPROVIDER_ENUM_CONTEXT)EnumContext;
779 
780     /* Calculate ProviderName string size */
781     INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0;
782     INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR);
783 
784     /* Copy the information */
785     NSProviderInfoFromContext(Entry, Context);
786     Context->BufferUsed += Context->Unicode ? (sizeof(WSANAMESPACE_INFOW)+size2) : (sizeof(WSANAMESPACE_INFOA)+size2);
787 
788     /* Continue enumeration */
789     return TRUE;
790 }
791 
792 INT
793 WSAAPI
WSAEnumNameSpaceProvidersInternal(IN OUT LPDWORD lpdwBufferLength,OUT LPWSANAMESPACE_INFOA lpnspBuffer,BOOLEAN Unicode)794 WSAEnumNameSpaceProvidersInternal(IN OUT LPDWORD lpdwBufferLength,
795     OUT LPWSANAMESPACE_INFOA lpnspBuffer, BOOLEAN Unicode)
796 {
797     INT Status;
798     PWSPROCESS WsProcess;
799     PNSCATALOG Catalog;
800     NSPROVIDER_ENUM_CONTEXT Context;
801 
802     DPRINT("WSAEnumNameSpaceProvidersInternal: %lx\n", lpnspBuffer);
803 
804     if (!lpdwBufferLength)
805     {
806         WSASetLastError(WSAEFAULT);
807         return SOCKET_ERROR;
808     }
809     WsProcess = WsGetProcess();
810     /* Create a catalog object from the current one */
811     Catalog = WsProcGetNsCatalog(WsProcess);
812     if (!Catalog)
813     {
814         /* Fail if we couldn't */
815         WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
816         return SOCKET_ERROR;
817     }
818 
819     Context.ProtocolBuffer = lpnspBuffer;
820     Context.BufferLength = lpnspBuffer ? *lpdwBufferLength : 0;
821     Context.BufferUsed = 0;
822     Context.Count = 0;
823     Context.Unicode = Unicode;
824     Context.ErrorCode = ERROR_SUCCESS;
825 
826     WsNcEnumerateCatalogItems(Catalog, NSProvidersEnumerationProc, &Context);
827 
828     /* Get status */
829     Status = Context.Count;
830 
831     /* Check the error code */
832     if (Context.ErrorCode == ERROR_SUCCESS)
833     {
834         /* Check if enough space was available */
835         if (Context.BufferLength < Context.BufferUsed)
836         {
837             /* Fail and tell them how much we need */
838             *lpdwBufferLength = Context.BufferUsed;
839             WSASetLastError(WSAEFAULT);
840             Status = SOCKET_ERROR;
841         }
842     }
843     else
844     {
845         /* Failure, normalize error */
846         Status = SOCKET_ERROR;
847         WSASetLastError(Context.ErrorCode);
848     }
849 
850     /* Return */
851     return Status;
852 }
853 
854 /*
855  * @implemented
856  */
857 INT
858 WSAAPI
WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength,OUT LPWSANAMESPACE_INFOA lpnspBuffer)859 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength,
860                            OUT LPWSANAMESPACE_INFOA lpnspBuffer)
861 {
862     DPRINT("WSAEnumNameSpaceProvidersA: %lx\n", lpnspBuffer);
863     return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, FALSE);
864 }
865 
866 /*
867  * @implemented
868  */
869 INT
870 WSAAPI
WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength,OUT LPWSANAMESPACE_INFOW lpnspBuffer)871 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength,
872                            OUT LPWSANAMESPACE_INFOW lpnspBuffer)
873 {
874     DPRINT("WSAEnumNameSpaceProvidersW: %lx\n", lpnspBuffer);
875     return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, TRUE);
876 }
877 
878 /*
879  * @implemented
880  */
881 INT
882 WSAAPI
WSAStringToAddressA(IN LPSTR AddressString,IN INT AddressFamily,IN LPWSAPROTOCOL_INFOA lpProtocolInfo,OUT LPSOCKADDR lpAddress,IN OUT LPINT lpAddressLength)883 WSAStringToAddressA(IN LPSTR AddressString,
884                     IN INT AddressFamily,
885                     IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
886                     OUT LPSOCKADDR lpAddress,
887                     IN OUT  LPINT lpAddressLength)
888 {
889     PWSPROCESS Process;
890     PWSTHREAD Thread;
891     INT ErrorCode, Status;
892     DWORD CatalogEntryId;
893     PTCATALOG Catalog;
894     PTCATALOG_ENTRY CatalogEntry;
895     LPWSTR UnicodeString;
896     DWORD Length = (DWORD)strlen(AddressString) + 1;
897 
898     DPRINT("WSAStringToAddressA: %s\n", AddressString);
899 
900     /* Enter prolog */
901     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
902     {
903         /* Leave now */
904         SetLastError(ErrorCode);
905         return SOCKET_ERROR;
906     }
907 
908     /* Allocate the unicode string */
909     UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2);
910     if (!UnicodeString)
911     {
912         /* No memory; fail */
913         SetLastError(WSAENOBUFS);
914         return SOCKET_ERROR;
915     }
916 
917     /* Convert the string */
918     MultiByteToWideChar(CP_ACP, 0, AddressString, -1, UnicodeString, Length);
919 
920     /* Get the catalog */
921     Catalog = WsProcGetTCatalog(Process);
922 
923     /* Check if we got custom protocol info */
924     if (lpProtocolInfo)
925     {
926         /* Get the entry ID */
927         CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
928 
929         /* Get the entry associated with it */
930         ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
931                                                    CatalogEntryId,
932                                                    &CatalogEntry);
933     }
934     else
935     {
936         /* Get it from the address family */
937         ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry);
938     }
939 
940     /* Check for success */
941     if (ErrorCode == ERROR_SUCCESS)
942     {
943         /* Call the provider */
944         Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(UnicodeString,
945                                                               AddressFamily,
946                                                               &CatalogEntry->
947                                                               ProtocolInfo,
948                                                               lpAddress,
949                                                               lpAddressLength,
950                                                               &ErrorCode);
951 
952         /* Dereference the entry */
953         WsTcEntryDereference(CatalogEntry);
954 
955         /* Free the unicode string */
956         HeapFree(WsSockHeap, 0, UnicodeString);
957 
958         /* Check for success and return */
959         if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
960     }
961     else
962     {
963         /* Free the unicode string */
964         HeapFree(WsSockHeap, 0, UnicodeString);
965     }
966 
967     /* Set the error and return */
968     SetLastError(ErrorCode);
969     return SOCKET_ERROR;
970 }
971 
972 /*
973  * @implemented
974  */
975 INT
976 WSAAPI
WSAStringToAddressW(IN LPWSTR AddressString,IN INT AddressFamily,IN LPWSAPROTOCOL_INFOW lpProtocolInfo,OUT LPSOCKADDR lpAddress,IN OUT LPINT lpAddressLength)977 WSAStringToAddressW(IN LPWSTR AddressString,
978                     IN INT AddressFamily,
979                     IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
980                     OUT LPSOCKADDR lpAddress,
981                     IN OUT LPINT lpAddressLength)
982 {
983     PWSPROCESS Process;
984     PWSTHREAD Thread;
985     INT ErrorCode, Status;
986     DWORD CatalogEntryId;
987     PTCATALOG Catalog;
988     PTCATALOG_ENTRY CatalogEntry;
989 
990     DPRINT("WSAStringToAddressW: %S\n", AddressString);
991 
992     /* Enter prolog */
993     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
994     {
995         /* Leave now */
996         SetLastError(ErrorCode);
997         return SOCKET_ERROR;
998     }
999 
1000     /* Get the catalog */
1001     Catalog = WsProcGetTCatalog(Process);
1002 
1003     /* Check if we got custom protocol info */
1004     if (lpProtocolInfo)
1005     {
1006         /* Get the entry ID */
1007         CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
1008 
1009         /* Get the entry associated with it */
1010         ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
1011                                                    CatalogEntryId,
1012                                                    &CatalogEntry);
1013     }
1014     else
1015     {
1016         /* Get it from the address family */
1017         ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry);
1018     }
1019 
1020     /* Check for success */
1021     if (ErrorCode == ERROR_SUCCESS)
1022     {
1023         /* Call the provider */
1024         Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(AddressString,
1025                                                                       AddressFamily,
1026                                                                       &CatalogEntry->
1027                                                                       ProtocolInfo,
1028                                                                       lpAddress,
1029                                                                       lpAddressLength,
1030                                                                       &ErrorCode);
1031 
1032         /* Dereference the entry */
1033         WsTcEntryDereference(CatalogEntry);
1034 
1035         /* Check for success and return */
1036         if (Status == ERROR_SUCCESS) return ERROR_SUCCESS;
1037     }
1038 
1039     /* Set the error and return */
1040     SetLastError(ErrorCode);
1041     return SOCKET_ERROR;
1042 }
1043