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