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