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 and Resolution Support
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
23 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress
,
24 IN DWORD dwAddressLength
,
25 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
26 OUT LPSTR lpszAddressString
,
27 IN OUT LPDWORD lpdwAddressStringLength
)
31 INT ErrorCode
, Status
;
34 PTCATALOG_ENTRY CatalogEntry
;
36 DWORD Length
= *lpdwAddressStringLength
;
38 DPRINT("WSAAddressToStringA: %p\n", lpsaAddress
);
41 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
44 SetLastError(ErrorCode
);
48 /* Allocate the unicode string */
49 UnicodeString
= HeapAlloc(WsSockHeap
, 0, Length
* 2);
53 SetLastError(WSAENOBUFS
);
58 Catalog
= WsProcGetTCatalog(Process
);
60 /* Check if we got custom protocol info */
63 /* Get the entry ID */
64 CatalogEntryId
= lpProtocolInfo
->dwCatalogEntryId
;
66 /* Get the entry associated with it */
67 ErrorCode
= WsTcGetEntryFromCatalogEntryId(Catalog
,
73 /* Get it from the address family */
74 ErrorCode
= WsTcGetEntryFromAf(Catalog
,
75 lpsaAddress
->sa_family
,
79 /* Check for success */
80 if (ErrorCode
== ERROR_SUCCESS
)
82 /* Call the provider */
83 Status
= CatalogEntry
->Provider
->Service
.lpWSPAddressToString(lpsaAddress
,
88 lpdwAddressStringLength
,
90 if (Status
== ERROR_SUCCESS
)
92 /* Convert the string */
93 WideCharToMultiByte(CP_ACP
,
103 /* Dereference the entry */
104 WsTcEntryDereference(CatalogEntry
);
106 /* Free the unicode string */
107 HeapFree(WsSockHeap
, 0, UnicodeString
);
109 /* Check for success and return */
110 if (Status
== ERROR_SUCCESS
) return ERROR_SUCCESS
;
114 /* Free the unicode string */
115 HeapFree(WsSockHeap
, 0, UnicodeString
);
118 /* Set the error and return */
119 SetLastError(ErrorCode
);
128 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
129 IN DWORD dwAddressLength
,
130 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
131 OUT LPWSTR lpszAddressString
,
132 IN OUT LPDWORD lpdwAddressStringLength
)
136 INT ErrorCode
, Status
;
137 DWORD CatalogEntryId
;
139 PTCATALOG_ENTRY CatalogEntry
;
141 DPRINT("WSAAddressToStringW: %p\n", lpsaAddress
);
144 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
147 SetLastError(ErrorCode
);
151 /* Get the catalog */
152 Catalog
= WsProcGetTCatalog(Process
);
154 /* Check if we got custom protocol info */
157 /* Get the entry ID */
158 CatalogEntryId
= lpProtocolInfo
->dwCatalogEntryId
;
160 /* Get the entry associated with it */
161 ErrorCode
= WsTcGetEntryFromCatalogEntryId(Catalog
,
167 /* Get it from the address family */
168 ErrorCode
= WsTcGetEntryFromAf(Catalog
,
169 lpsaAddress
->sa_family
,
173 /* Check for success */
174 if (ErrorCode
== ERROR_SUCCESS
)
176 /* Call the provider */
177 Status
= CatalogEntry
->Provider
->Service
.lpWSPAddressToString(lpsaAddress
,
182 lpdwAddressStringLength
,
185 /* Dereference the entry */
186 WsTcEntryDereference(CatalogEntry
);
188 /* Check for success and return */
189 if (Status
== ERROR_SUCCESS
) return ERROR_SUCCESS
;
192 /* Set the error and return */
193 SetLastError(ErrorCode
);
202 WSALookupServiceEnd(IN HANDLE hLookup
)
207 PNSQUERY Query
= hLookup
;
209 DPRINT("WSALookupServiceEnd: %lx\n", hLookup
);
212 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
215 SetLastError(ErrorCode
);
219 /* Check for a valid handle, then validate and reference it */
220 if (IsBadReadPtr(Query
, sizeof(*Query
)) || !WsNqValidateAndReference(Query
))
223 SetLastError(WSA_INVALID_HANDLE
);
228 ErrorCode
= WsNqLookupServiceEnd(Query
);
230 /* Remove the validation reference */
231 WsNqDereference(Query
);
233 /* Remove the keep-alive */
234 WsNqDereference(Query
);
237 return ERROR_SUCCESS
;
245 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
246 IN DWORD dwControlFlags
,
247 OUT LPHANDLE lphLookup
)
250 LPWSAQUERYSETW UnicodeQuerySet
= NULL
;
251 DWORD UnicodeQuerySetSize
= 0;
253 DPRINT("WSALookupServiceBeginA: %p\n", lpqsRestrictions
);
256 if (IsBadReadPtr(lpqsRestrictions
, sizeof(*lpqsRestrictions
)) ||
257 IsBadReadPtr(lpqsRestrictions
->lpServiceClassId
, sizeof(*lpqsRestrictions
->lpServiceClassId
)))
260 SetLastError(WSAEFAULT
);
264 /* Clear the reserved fields */
265 lpqsRestrictions
->dwOutputFlags
= 0;
266 lpqsRestrictions
->lpszComment
= NULL
;
267 lpqsRestrictions
->dwNumberOfCsAddrs
= 0;
269 /* Find out the side we'll need */
270 ErrorCode
= MapAnsiQuerySetToUnicode(lpqsRestrictions
,
271 &UnicodeQuerySetSize
,
274 /* We should've failed */
275 if (ErrorCode
== WSAEFAULT
)
277 /* Allocate the buffer we'll need */
278 UnicodeQuerySet
= HeapAlloc(WsSockHeap
, 0, UnicodeQuerySetSize
);
281 /* Do the conversion for real */
282 ErrorCode
= MapAnsiQuerySetToUnicode(lpqsRestrictions
,
283 &UnicodeQuerySetSize
,
285 if (ErrorCode
== ERROR_SUCCESS
)
287 /* Now call the Unicode function */
288 ErrorCode
= WSALookupServiceBeginW(UnicodeQuerySet
,
293 /* Free our buffer */
294 HeapFree(WsSockHeap
, 0, UnicodeQuerySet
);
298 /* No memory to allocate */
299 ErrorCode
= WSAEFAULT
;
303 /* Set the error in case of failure */
304 if (ErrorCode
!= ERROR_SUCCESS
)
305 SetLastError(ErrorCode
);
307 /* Return to caller */
308 return ErrorCode
== ERROR_SUCCESS
? ErrorCode
: SOCKET_ERROR
;
316 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
317 IN DWORD dwControlFlags
,
318 OUT LPHANDLE lphLookup
)
325 DPRINT("WSALookupServiceBeginW: %p\n", lpqsRestrictions
);
328 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
331 SetLastError(ErrorCode
);
335 /* Verify pointers */
336 if (IsBadWritePtr(lphLookup
, sizeof(*lphLookup
)) ||
337 IsBadReadPtr(lpqsRestrictions
, sizeof(*lpqsRestrictions
)) ||
338 IsBadReadPtr(lpqsRestrictions
->lpServiceClassId
, sizeof(*lpqsRestrictions
->lpServiceClassId
)))
340 /* They are invalid; fail */
341 SetLastError(WSAEFAULT
);
345 /* Create a new query object */
346 if ((Query
= WsNqAllocate()))
349 WsNqInitialize(Query
);
352 ErrorCode
= WsNqLookupServiceBegin(Query
,
355 WsProcGetNsCatalog(Process
));
357 /* Check for success */
358 if (ErrorCode
== ERROR_SUCCESS
)
360 /* Return the handle */
373 ErrorCode
= SOCKET_ERROR
;
374 SetLastError(WSAENOBUFS
);
386 WSALookupServiceNextW(IN HANDLE hLookup
,
387 IN DWORD dwControlFlags
,
388 IN OUT LPDWORD lpdwBufferLength
,
389 OUT LPWSAQUERYSETW lpqsResults
)
394 PNSQUERY Query
= hLookup
;
396 DPRINT("WSALookupServiceNextW: %lx\n", hLookup
);
399 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
402 SetLastError(ErrorCode
);
406 /* Verify pointers */
407 if (IsBadReadPtr(lpdwBufferLength
, sizeof(*lpdwBufferLength
)) ||
408 IsBadWritePtr(lpqsResults
, sizeof(*lpqsResults
)))
410 /* It is invalid; fail */
411 SetLastError(WSAEFAULT
);
415 /* Check for a valid handle, then validate and reference it */
416 if (IsBadReadPtr(Query
, sizeof(*Query
)) || !WsNqValidateAndReference(Query
))
419 SetLastError(WSA_INVALID_HANDLE
);
424 ErrorCode
= WsNqLookupServiceNext(Query
,
429 /* Remove the validation reference */
430 WsNqDereference(Query
);
441 WSALookupServiceNextA(IN HANDLE hLookup
,
442 IN DWORD dwControlFlags
,
443 IN OUT LPDWORD lpdwBufferLength
,
444 OUT LPWSAQUERYSETA lpqsResults
)
446 LPWSAQUERYSETW UnicodeQuerySet
;
447 DWORD UnicodeQuerySetSize
;
450 DPRINT("WSALookupServiceNextA: %lx\n", hLookup
);
452 /* Verify pointers */
453 if (IsBadReadPtr(lpdwBufferLength
, sizeof(*lpdwBufferLength
)) ||
454 IsBadWritePtr(lpqsResults
, sizeof(*lpqsResults
)))
456 /* It is invalid; fail */
457 SetLastError(WSAEFAULT
);
461 UnicodeQuerySetSize
= *lpdwBufferLength
;
463 /* Check how much the user is giving */
464 if (UnicodeQuerySetSize
>= sizeof(WSAQUERYSETW
))
466 /* Allocate the buffer we'll use */
467 UnicodeQuerySet
= HeapAlloc(WsSockHeap
, 0, UnicodeQuerySetSize
);
468 if (!UnicodeQuerySet
) UnicodeQuerySetSize
= 0;
472 /* His buffer is too small */
473 UnicodeQuerySetSize
= 0;
474 UnicodeQuerySet
= NULL
;
477 /* Call the Unicode Function */
478 ErrorCode
= WSALookupServiceNextW(hLookup
,
480 &UnicodeQuerySetSize
,
482 if (ErrorCode
== ERROR_SUCCESS
)
484 /* Not convert to ANSI */
485 ErrorCode
= MapUnicodeQuerySetToAnsi(UnicodeQuerySet
,
488 if (ErrorCode
!= ERROR_SUCCESS
) SetLastError(ErrorCode
);
492 /* Check if we ran out of space */
493 if (GetLastError() == WSAEFAULT
)
495 /* Return how much space we'll need, including padding */
496 *lpdwBufferLength
= UnicodeQuerySetSize
+
497 ((sizeof(ULONG
) * 6) - (6 * 1));
501 /* If we had a local buffer, free it */
502 if (UnicodeQuerySet
) HeapFree(WsSockHeap
, 0, UnicodeQuerySet
);
504 /* Return to caller */
505 return ErrorCode
== ERROR_SUCCESS
? ErrorCode
: SOCKET_ERROR
;
513 WSANSPIoctl(HANDLE hLookup
,
519 LPDWORD lpcbBytesReturned
,
520 LPWSACOMPLETION lpCompletion
)
522 DPRINT("WSANSPIoctl: %lx\n", hLookup
);
531 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
533 DPRINT("WSARemoveServiceClass: %lx\n", lpServiceClassId
);
534 SetLastError(WSAEINVAL
);
543 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
544 IN WSAESETSERVICEOP essOperation
,
545 IN DWORD dwControlFlags
)
547 DPRINT("WSASetServiceA: %lx\n", lpqsRegInfo
);
548 SetLastError(WSAEINVAL
);
557 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
558 IN WSAESETSERVICEOP essOperation
,
559 IN DWORD dwControlFlags
)
561 DPRINT("WSASetServiceW: %lx\n", lpqsRegInfo
);
562 SetLastError(WSAEINVAL
);
571 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
572 IN LPGUID lpServiceClassId
,
573 IN OUT LPDWORD lpdwBufferLength
,
574 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
576 DPRINT("WSAGetServiceClassInfoA: %lx\n", lpProviderId
);
577 SetLastError(WSAEINVAL
);
586 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
587 IN LPGUID lpServiceClassId
,
588 IN OUT LPDWORD lpdwBufferLength
,
589 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
591 DPRINT("WSAGetServiceClassInfoW: %lx\n", lpProviderId
);
592 SetLastError(WSAEINVAL
);
601 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
602 OUT LPSTR lpszServiceClassName
,
603 IN OUT LPDWORD lpdwBufferLength
)
605 DPRINT("WSAGetServiceClassNameByClassIdA: %lx\n", lpServiceClassId
);
606 SetLastError(WSAEINVAL
);
615 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
616 OUT LPWSTR lpszServiceClassName
,
617 IN OUT LPDWORD lpdwBufferLength
)
619 DPRINT("WSAGetServiceClassNameByClassIdW: %lx\n", lpServiceClassId
);
620 SetLastError(WSAEINVAL
);
629 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
631 DPRINT("WSAInstallServiceClassA: %lx\n", lpServiceClassInfo
);
632 SetLastError(WSAEINVAL
);
641 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
643 DPRINT("WSAInstallServiceClassW: %lx\n", lpServiceClassInfo
);
644 SetLastError(WSAEINVAL
);
650 NSProviderInfoFromContext(IN PNSCATALOG_ENTRY Entry
,
651 IN PNSPROVIDER_ENUM_CONTEXT Context
)
653 INT size
= Context
->Unicode
? sizeof(WSANAMESPACE_INFOW
) : sizeof(WSANAMESPACE_INFOA
);
654 /* Calculate ProviderName string size */
655 INT size1
= Entry
->ProviderName
? wcslen(Entry
->ProviderName
) + 1 : 0;
656 INT size2
= Context
->Unicode
? size1
* sizeof(WCHAR
) : size1
* sizeof(CHAR
);
657 WSANAMESPACE_INFOW infoW
;
658 /* Fill NS Provider data */
659 infoW
.dwNameSpace
= Entry
->NamespaceId
;
660 infoW
.dwVersion
= Entry
->Version
;
661 infoW
.fActive
= Entry
->Enabled
;
662 RtlMoveMemory(&infoW
.NSProviderId
,
664 sizeof(infoW
.NSProviderId
));
667 /* Calculate ProviderName string pointer */
668 infoW
.lpszIdentifier
= (LPWSTR
)((ULONG_PTR
)Context
->ProtocolBuffer
+
669 Context
->BufferUsed
+ size
);
673 infoW
.lpszIdentifier
= NULL
;
676 /* Check if we'll have space */
677 if ((Context
->BufferUsed
+ size
+ size2
) <=
678 (Context
->BufferLength
))
681 RtlMoveMemory((PVOID
)((ULONG_PTR
)Context
->ProtocolBuffer
+
682 Context
->BufferUsed
),
687 /* Entry->ProviderName is LPWSTR */
688 if (Context
->Unicode
)
690 RtlMoveMemory((PVOID
)((ULONG_PTR
)Context
->ProtocolBuffer
+
691 Context
->BufferUsed
+ size
),
697 /* Call the conversion function */
698 WideCharToMultiByte(CP_ACP
,
702 (LPSTR
)((ULONG_PTR
)Context
->ProtocolBuffer
+
703 Context
->BufferUsed
+ size
),
711 /* Increase the count */
718 NSProvidersEnumerationProc(PVOID EnumContext
,
719 PNSCATALOG_ENTRY Entry
)
721 PNSPROVIDER_ENUM_CONTEXT Context
= (PNSPROVIDER_ENUM_CONTEXT
)EnumContext
;
723 /* Calculate ProviderName string size */
724 INT size1
= Entry
->ProviderName
? wcslen(Entry
->ProviderName
) + 1 : 0;
725 INT size2
= Context
->Unicode
? size1
* sizeof(WCHAR
) : size1
* sizeof(CHAR
);
727 /* Copy the information */
728 NSProviderInfoFromContext(Entry
, Context
);
729 Context
->BufferUsed
+= Context
->Unicode
? (sizeof(WSANAMESPACE_INFOW
)+size2
) : (sizeof(WSANAMESPACE_INFOA
)+size2
);
731 /* Continue enumeration */
737 WSAEnumNameSpaceProvidersInternal(IN OUT LPDWORD lpdwBufferLength
,
738 OUT LPWSANAMESPACE_INFOA lpnspBuffer
, BOOLEAN Unicode
)
741 PWSPROCESS WsProcess
;
743 NSPROVIDER_ENUM_CONTEXT Context
;
745 DPRINT("WSAEnumNameSpaceProvidersInternal: %lx\n", lpnspBuffer
);
747 if (!lpdwBufferLength
)
749 WSASetLastError(WSAEFAULT
);
752 WsProcess
= WsGetProcess();
753 /* Create a catalog object from the current one */
754 Catalog
= WsProcGetNsCatalog(WsProcess
);
757 /* Fail if we couldn't */
758 WSASetLastError(WSA_NOT_ENOUGH_MEMORY
);
762 Context
.ProtocolBuffer
= lpnspBuffer
;
763 Context
.BufferLength
= lpnspBuffer
? *lpdwBufferLength
: 0;
764 Context
.BufferUsed
= 0;
766 Context
.Unicode
= Unicode
;
767 Context
.ErrorCode
= ERROR_SUCCESS
;
769 WsNcEnumerateCatalogItems(Catalog
, NSProvidersEnumerationProc
, &Context
);
772 Status
= Context
.Count
;
774 /* Check the error code */
775 if (Context
.ErrorCode
== ERROR_SUCCESS
)
777 /* Check if enough space was available */
778 if (Context
.BufferLength
< Context
.BufferUsed
)
780 /* Fail and tell them how much we need */
781 *lpdwBufferLength
= Context
.BufferUsed
;
782 WSASetLastError(WSAEFAULT
);
783 Status
= SOCKET_ERROR
;
788 /* Failure, normalize error */
789 Status
= SOCKET_ERROR
;
790 WSASetLastError(Context
.ErrorCode
);
802 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
803 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
805 DPRINT("WSAEnumNameSpaceProvidersA: %lx\n", lpnspBuffer
);
806 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength
, (LPWSANAMESPACE_INFOA
)lpnspBuffer
, FALSE
);
814 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
815 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
817 DPRINT("WSAEnumNameSpaceProvidersW: %lx\n", lpnspBuffer
);
818 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength
, (LPWSANAMESPACE_INFOA
)lpnspBuffer
, TRUE
);
826 WSAStringToAddressA(IN LPSTR AddressString
,
827 IN INT AddressFamily
,
828 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
829 OUT LPSOCKADDR lpAddress
,
830 IN OUT LPINT lpAddressLength
)
834 INT ErrorCode
, Status
;
835 DWORD CatalogEntryId
;
837 PTCATALOG_ENTRY CatalogEntry
;
838 LPWSTR UnicodeString
;
839 DWORD Length
= (DWORD
)strlen(AddressString
) + 1;
841 DPRINT("WSAStringToAddressA: %s\n", AddressString
);
844 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
847 SetLastError(ErrorCode
);
851 /* Allocate the unicode string */
852 UnicodeString
= HeapAlloc(WsSockHeap
, 0, Length
* 2);
855 /* No memory; fail */
856 SetLastError(WSAENOBUFS
);
860 /* Convert the string */
861 MultiByteToWideChar(CP_ACP
, 0, AddressString
, -1, UnicodeString
, Length
);
863 /* Get the catalog */
864 Catalog
= WsProcGetTCatalog(Process
);
866 /* Check if we got custom protocol info */
869 /* Get the entry ID */
870 CatalogEntryId
= lpProtocolInfo
->dwCatalogEntryId
;
872 /* Get the entry associated with it */
873 ErrorCode
= WsTcGetEntryFromCatalogEntryId(Catalog
,
879 /* Get it from the address family */
880 ErrorCode
= WsTcGetEntryFromAf(Catalog
, AddressFamily
, &CatalogEntry
);
883 /* Check for success */
884 if (ErrorCode
== ERROR_SUCCESS
)
886 /* Call the provider */
887 Status
= CatalogEntry
->Provider
->Service
.lpWSPStringToAddress(UnicodeString
,
895 /* Dereference the entry */
896 WsTcEntryDereference(CatalogEntry
);
898 /* Free the unicode string */
899 HeapFree(WsSockHeap
, 0, UnicodeString
);
901 /* Check for success and return */
902 if (Status
== ERROR_SUCCESS
) return ERROR_SUCCESS
;
906 /* Free the unicode string */
907 HeapFree(WsSockHeap
, 0, UnicodeString
);
910 /* Set the error and return */
911 SetLastError(ErrorCode
);
920 WSAStringToAddressW(IN LPWSTR AddressString
,
921 IN INT AddressFamily
,
922 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
923 OUT LPSOCKADDR lpAddress
,
924 IN OUT LPINT lpAddressLength
)
928 INT ErrorCode
, Status
;
929 DWORD CatalogEntryId
;
931 PTCATALOG_ENTRY CatalogEntry
;
933 DPRINT("WSAStringToAddressW: %S\n", AddressString
);
936 if ((ErrorCode
= WsApiProlog(&Process
, &Thread
)) != ERROR_SUCCESS
)
939 SetLastError(ErrorCode
);
943 /* Get the catalog */
944 Catalog
= WsProcGetTCatalog(Process
);
946 /* Check if we got custom protocol info */
949 /* Get the entry ID */
950 CatalogEntryId
= lpProtocolInfo
->dwCatalogEntryId
;
952 /* Get the entry associated with it */
953 ErrorCode
= WsTcGetEntryFromCatalogEntryId(Catalog
,
959 /* Get it from the address family */
960 ErrorCode
= WsTcGetEntryFromAf(Catalog
, AddressFamily
, &CatalogEntry
);
963 /* Check for success */
964 if (ErrorCode
== ERROR_SUCCESS
)
966 /* Call the provider */
967 Status
= CatalogEntry
->Provider
->Service
.lpWSPStringToAddress(AddressString
,
975 /* Dereference the entry */
976 WsTcEntryDereference(CatalogEntry
);
978 /* Check for success and return */
979 if (Status
== ERROR_SUCCESS
) return ERROR_SUCCESS
;
982 /* Set the error and return */
983 SetLastError(ErrorCode
);