2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
5 * PURPOSE: Namespace APIs
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
10 #define __NO_CTYPE_INLINES
19 #ifndef MAX_HOSTNAME_LEN
20 #define MAX_HOSTNAME_LEN 256
23 /* Name resolution APIs */
30 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress
,
31 IN DWORD dwAddressLength
,
32 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
33 OUT LPSTR lpszAddressString
,
34 IN OUT LPDWORD lpdwAddressStringLength
)
38 WSASetLastError(WSASYSCALLFAILURE
);
48 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
49 IN DWORD dwAddressLength
,
50 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
51 OUT LPWSTR lpszAddressString
,
52 IN OUT LPDWORD lpdwAddressStringLength
)
56 WSASetLastError(WSASYSCALLFAILURE
);
66 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
67 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
71 WSASetLastError(WSASYSCALLFAILURE
);
81 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
82 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
86 WSASetLastError(WSASYSCALLFAILURE
);
96 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
97 IN LPGUID lpServiceClassId
,
98 IN OUT LPDWORD lpdwBufferLength
,
99 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
103 WSASetLastError(WSASYSCALLFAILURE
);
113 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
114 IN LPGUID lpServiceClassId
,
115 IN OUT LPDWORD lpdwBufferLength
,
116 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
120 WSASetLastError(WSASYSCALLFAILURE
);
130 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
131 OUT LPSTR lpszServiceClassName
,
132 IN OUT LPDWORD lpdwBufferLength
)
136 WSASetLastError(WSASYSCALLFAILURE
);
146 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
147 OUT LPWSTR lpszServiceClassName
,
148 IN OUT LPDWORD lpdwBufferLength
)
152 WSASetLastError(WSASYSCALLFAILURE
);
162 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
166 WSASetLastError(WSASYSCALLFAILURE
);
176 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
180 WSASetLastError(WSASYSCALLFAILURE
);
190 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
191 IN DWORD dwControlFlags
,
192 OUT LPHANDLE lphLookup
)
196 WSASetLastError(WSASYSCALLFAILURE
);
206 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
207 IN DWORD dwControlFlags
,
208 OUT LPHANDLE lphLookup
)
212 WSASetLastError(WSASYSCALLFAILURE
);
222 WSALookupServiceEnd(IN HANDLE hLookup
)
226 WSASetLastError(WSASYSCALLFAILURE
);
236 WSALookupServiceNextA(IN HANDLE hLookup
,
237 IN DWORD dwControlFlags
,
238 IN OUT LPDWORD lpdwBufferLength
,
239 OUT LPWSAQUERYSETA lpqsResults
)
243 WSASetLastError(WSASYSCALLFAILURE
);
253 WSALookupServiceNextW(IN HANDLE hLookup
,
254 IN DWORD dwControlFlags
,
255 IN OUT LPDWORD lpdwBufferLength
,
256 OUT LPWSAQUERYSETW lpqsResults
)
260 WSASetLastError(WSASYSCALLFAILURE
);
270 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
274 WSASetLastError(WSASYSCALLFAILURE
);
284 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
285 IN WSAESETSERVICEOP essOperation
,
286 IN DWORD dwControlFlags
)
290 WSASetLastError(WSASYSCALLFAILURE
);
300 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
301 IN WSAESETSERVICEOP essOperation
,
302 IN DWORD dwControlFlags
)
306 WSASetLastError(WSASYSCALLFAILURE
);
316 WSAStringToAddressA(IN LPSTR AddressString
,
317 IN INT AddressFamily
,
318 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
319 OUT LPSOCKADDR lpAddress
,
320 IN OUT LPINT lpAddressLength
)
324 LPWSAPROTOCOL_INFOW lpProtoInfoW
= NULL
;
326 len
= MultiByteToWideChar(CP_ACP
,
333 szTemp
= HeapAlloc(GetProcessHeap(),
335 len
* sizeof(WCHAR
));
337 MultiByteToWideChar(CP_ACP
,
346 len
= WSAPROTOCOL_LEN
+1;
347 lpProtoInfoW
= HeapAlloc(GetProcessHeap(),
349 len
* sizeof(WCHAR
) );
353 sizeof(LPWSAPROTOCOL_INFOA
));
355 MultiByteToWideChar(CP_ACP
,
357 lpProtocolInfo
->szProtocol
,
359 lpProtoInfoW
->szProtocol
,
363 ret
= WSAStringToAddressW(szTemp
,
369 HeapFree(GetProcessHeap(),
374 HeapFree(GetProcessHeap(),
378 WSASetLastError(ret
);
389 WSAStringToAddressW(IN LPWSTR AddressString
,
390 IN INT AddressFamily
,
391 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
392 OUT LPSOCKADDR lpAddress
,
393 IN OUT LPINT lpAddressLength
)
399 SOCKADDR_IN
*sockaddr
;
401 if (!lpAddressLength
|| !lpAddress
|| !AddressString
)
403 WSASetLastError(WSAEINVAL
);
407 sockaddr
= (SOCKADDR_IN
*) lpAddress
;
409 /* Set right adress family */
410 if (lpProtocolInfo
!=NULL
)
411 sockaddr
->sin_family
= lpProtocolInfo
->iAddressFamily
;
413 else sockaddr
->sin_family
= AddressFamily
;
416 if (AddressFamily
== AF_INET
)
418 if (*lpAddressLength
< (INT
)sizeof(SOCKADDR_IN
))
420 *lpAddressLength
= sizeof(SOCKADDR_IN
);
425 // translate ip string to ip
427 /* rest sockaddr.sin_addr.s_addr
428 for we need to be sure it is zero when we come to while */
429 memset(lpAddress
,0,sizeof(SOCKADDR_IN
));
431 /* Set right adress family */
432 sockaddr
->sin_family
= AF_INET
;
434 /* Get port number */
435 pos
= wcscspn(AddressString
,L
":") + 1;
437 if (pos
< (int)wcslen(AddressString
))
438 sockaddr
->sin_port
= wcstol(&AddressString
[pos
],
443 sockaddr
->sin_port
= 0;
449 while (pos
< (int)wcslen(AddressString
))
451 inetaddr
= (inetaddr
<<8) + ((UCHAR
)wcstol(&AddressString
[pos
],
454 pos
+= wcscspn( &AddressString
[pos
],L
".") +1 ;
458 sockaddr
->sin_addr
.s_addr
= inetaddr
;
463 WSASetLastError(res
);
468 void check_hostent(struct hostent
**he
)
470 struct hostent
*new_he
;
472 WS_DbgPrint(MID_TRACE
,("*he: %x\n",*he
));
476 new_he
= HeapAlloc(GlobalHeap
,
478 sizeof(struct hostent
) + MAX_HOSTNAME_LEN
+ 1);
480 new_he
->h_name
= (PCHAR
)(new_he
+ 1);
481 new_he
->h_aliases
= 0;
482 new_he
->h_addrtype
= 0; // AF_INET
483 new_he
->h_length
= 0; // sizeof(in_addr)
484 new_he
->h_addr_list
= HeapAlloc(GlobalHeap
,
488 RtlZeroMemory(new_he
->h_addr_list
,
494 void populate_hostent(struct hostent
*he
, char* name
, DNS_A_DATA addr
)
498 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
499 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
505 if( !he
->h_aliases
) {
506 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
507 he
->h_aliases
[0] = 0;
509 he
->h_addrtype
= AF_INET
;
510 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
512 if( he
->h_addr_list
[0] )
519 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
521 MAX_HOSTNAME_LEN
+ 1);
523 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
525 RtlCopyMemory(he
->h_addr_list
[0],
526 (char*)&addr
.IpAddress
,
527 sizeof(addr
.IpAddress
));
529 he
->h_addr_list
[1] = 0;
533 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
534 void free_hostent(struct hostent
*he
)
542 next
= he
->h_aliases
[0];
543 while(next
) { HFREE(next
); next
++; }
547 next
= he
->h_addr_list
[0];
548 while(next
) { HFREE(next
); next
++; }
550 HFREE(he
->h_addr_list
);
551 HFREE(he
->h_aliases
);
556 /* WinSock 1.1 compatible name resolution APIs */
563 gethostbyaddr(IN CONST CHAR FAR
* addr
,
569 return (LPHOSTENT
)NULL
;
573 Assumes rfc 1123 - adam *
575 addr[0] = inet_addr(name);
576 strcpy( hostname, name );
577 if(addr[0] == 0xffffffff) return NULL;
578 he.h_addr_list = (void *)addr;
579 he.h_name = hostname;
581 he.h_addrtype = AF_INET;
582 he.h_length = sizeof(addr);
586 From the MSDN Platform SDK: Windows Sockets 2
587 "The gethostbyname function cannot resolve IP address strings passed to it.
588 Such a request is treated exactly as if an unknown host name were passed."
591 Defferring to the the documented behaviour, rather than the unix behaviour
592 What if the hostname is in the HOSTS file? see getservbyname
597 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
598 /* see ws2_32.h, winsock2.h*/
599 /*getnetworkparameters - iphlp api */
603 servent -- w32api/include/winsock2.h
604 PWINSOCK_THREAD_BLOCK -- ws2_32.h
605 dllmain.c -- threadlocal memory allocation / deallocation
610 /* lib/adns/src/adns.h XXX */
620 #define h_addr h_addr_list[0]
630 struct hostent defined in w32api/include/winsock2.h
633 void free_servent(struct servent
* s
)
637 next
= s
->s_aliases
[0];
638 while(next
) { HFREE(next
); next
++; }
648 gethostbyname(IN CONST CHAR FAR
* name
)
657 typedef enum addr_type addr_type
;
661 DNS_STATUS dns_status
= {0};
662 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
664 PWINSOCK_THREAD_BLOCK p
;
668 p
= NtCurrentTeb()->WinSockData
;
672 WSASetLastError( WSANOTINITIALISED
);
676 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
678 /* Hostname NULL - behave like gethostname */
681 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
687 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
691 /* Is it an IPv6 address? */
692 found
= strstr(name
, ":");
699 /* Is it an IPv4 address? */
700 if (!isalpha(name
[0]))
706 addr
= GH_RFC1123_DNS
;
708 /* Broken out in case we want to get fancy later */
713 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
718 WSASetLastError(WSAEFAULT
);
722 /* Note: If passed an IP address, MSDN says that gethostbyname()
723 treats it as an unknown host.
724 This is different from the unix implementation. Use inet_addr()
728 /* DNS_TYPE_A: include/WinDNS.h */
729 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
730 dns_status
= DnsQuery_A(name
,
734 /* extra dns servers */ &dp
,
739 //ASSERT(dp->wType == DNS_TYPE_A);
740 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
743 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
746 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
752 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
753 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
754 populate_hostent(p
->Hostent
, (PCHAR
)curr
->pName
, curr
->Data
.A
);
755 DnsRecordListFree(dp
, DnsFreeRecordList
);
760 DnsRecordListFree(dp
, DnsFreeRecordList
);
764 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
766 WSASetLastError(WSAHOST_NOT_FOUND
);
772 WSASetLastError(WSANO_RECOVERY
);
777 WSASetLastError(WSANO_RECOVERY
);
786 gethostname(OUT CHAR FAR
* name
,
789 DWORD size
= namelen
;
791 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
796 WSASetLastError(WSAEFAULT
);
801 name
[namelen
-1] = '\0';
808 * XXX arty -- Partial implementation pending a better one. This one will
809 * do for normal purposes.#include <ws2_32.h>
811 * Return the address of a static LPPROTOENT corresponding to the named
812 * protocol. These structs aren't very interesting, so I'm not too ashamed
813 * to have this function work on builtins for now.
818 static CHAR
*no_aliases
= 0;
819 static PROTOENT protocols
[] =
821 {"icmp",&no_aliases
, IPPROTO_ICMP
},
822 {"tcp", &no_aliases
, IPPROTO_TCP
},
823 {"udp", &no_aliases
, IPPROTO_UDP
},
829 getprotobyname(IN CONST CHAR FAR
* name
)
832 for (i
= 0; protocols
[i
].p_name
; i
++)
834 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
835 return &protocols
[i
];
845 getprotobynumber(IN INT number
)
848 for (i
= 0; protocols
[i
].p_name
; i
++)
850 if (protocols
[i
].p_proto
== number
)
851 return &protocols
[i
];
856 #define SKIPWS(ptr,act) \
857 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
858 #define SKIPANDMARKSTR(ptr,act) \
859 {while(*ptr && !isspace(*ptr)) ptr++; \
860 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
864 DecodeServEntFromString(IN PCHAR ServiceString
,
865 OUT PCHAR
*ServiceName
,
866 OUT PCHAR
*PortNumberStr
,
867 OUT PCHAR
*ProtocolStr
,
873 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
875 SKIPWS(ServiceString
, return FALSE
);
876 *ServiceName
= ServiceString
;
877 SKIPANDMARKSTR(ServiceString
, return FALSE
);
878 SKIPWS(ServiceString
, return FALSE
);
879 *PortNumberStr
= ServiceString
;
880 SKIPANDMARKSTR(ServiceString
, ;);
882 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
884 SKIPWS(ServiceString
, break);
887 SKIPANDMARKSTR(ServiceString
, ;);
888 if( strlen(ServiceString
) )
890 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
891 *Aliases
++ = ServiceString
;
898 *ProtocolStr
= strchr(*PortNumberStr
,'/');
899 if( !*ProtocolStr
) return FALSE
;
900 **ProtocolStr
= 0; (*ProtocolStr
)++;
902 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
903 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
909 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
916 getservbyname(IN CONST CHAR FAR
* name
,
917 IN CONST CHAR FAR
* proto
)
921 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
922 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
923 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
924 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
925 ProtocolStr
= 0, Comment
= 0;
926 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
927 UINT i
,SizeNeeded
= 0,
928 SystemDirSize
= sizeof(ServiceDBData
) - 1;
929 DWORD ReadSize
= 0, ValidData
= 0;
930 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
934 WSASetLastError( WSANOTINITIALISED
);
940 WSASetLastError( WSANO_RECOVERY
);
944 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
946 WSASetLastError( WSANO_RECOVERY
);
947 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
948 return NULL
; /* Can't get system directory */
951 strncat(SystemDirectory
,
952 ServicesFileLocation
,
955 ServicesFile
= CreateFileA(SystemDirectory
,
960 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
963 if( ServicesFile
== INVALID_HANDLE_VALUE
)
965 WSASetLastError( WSANO_RECOVERY
);
969 /* Scan the services file ...
971 * We will read up to BUFSIZ bytes per pass, until the buffer does not
972 * contain a full line, then we will try to read more.
974 * We fall from the loop if the buffer does not have a line terminator.
979 ReadFile(ServicesFile
,
980 ServiceDBData
+ ValidData
,
981 sizeof( ServiceDBData
) - ValidData
,
985 ValidData
+= ReadSize
;
987 NextLine
= ThisLine
= ServiceDBData
;
989 /* Find the beginning of the next line */
990 while(NextLine
< ServiceDBData
+ ValidData
&&
991 *NextLine
!= '\r' && *NextLine
!= '\n' )
996 /* Zero and skip, so we can treat what we have as a string */
997 if( NextLine
>= ServiceDBData
+ ValidData
)
1000 *NextLine
= 0; NextLine
++;
1002 Comment
= strchr( ThisLine
, '#' );
1003 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1005 if(DecodeServEntFromString(ThisLine
,
1010 WS2_INTERNAL_MAX_ALIAS
) &&
1011 !strcmp( ServiceName
, name
) &&
1012 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1015 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1017 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1018 (NextLine
- ThisLine
);
1022 /* Get rid of everything we read so far */
1023 while( NextLine
<= ServiceDBData
+ ValidData
&&
1024 isspace( *NextLine
) )
1029 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1030 ServiceDBData
+ ValidData
- NextLine
));
1032 memmove(ServiceDBData
,
1034 ServiceDBData
+ ValidData
- NextLine
);
1035 ValidData
-= NextLine
- ServiceDBData
;
1036 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1039 /* This we'll do no matter what */
1040 CloseHandle( ServicesFile
);
1044 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1045 WSASetLastError( WSANO_DATA
);
1049 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1051 /* Free previous getservbyname buffer, allocate bigger */
1052 if( p
->Getservbyname
)
1053 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1054 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1055 if( !p
->Getservbyname
)
1057 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1059 WSASetLastError( WSATRY_AGAIN
);
1062 p
->Getservbyname
->Size
= SizeNeeded
;
1066 memmove(p
->Getservbyname
->Data
,
1068 NextLine
- ThisLine
);
1070 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1071 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1072 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1076 for( i
= 0; Aliases
[i
]; i
++ )
1078 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1079 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1082 memcpy(p
->Getservbyname
,
1086 /* Create the struct proper */
1087 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1088 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1089 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1090 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1092 return &p
->Getservbyname
->ServerEntry
;
1101 getservbyport(IN INT port
,
1102 IN CONST CHAR FAR
* proto
)
1105 HANDLE ServicesFile
;
1106 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1107 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1108 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1109 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1110 ProtocolStr
= 0, Comment
= 0;
1111 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1112 UINT i
,SizeNeeded
= 0,
1113 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1114 DWORD ReadSize
= 0, ValidData
= 0;
1115 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1119 WSASetLastError( WSANOTINITIALISED
);
1125 WSASetLastError( WSANO_RECOVERY
);
1129 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1131 WSASetLastError( WSANO_RECOVERY
);
1132 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1133 return NULL
; /* Can't get system directory */
1136 strncat(SystemDirectory
,
1137 ServicesFileLocation
,
1140 ServicesFile
= CreateFileA(SystemDirectory
,
1145 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1148 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1150 WSASetLastError( WSANO_RECOVERY
);
1154 /* Scan the services file ...
1156 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1157 * contain a full line, then we will try to read more.
1159 * We fall from the loop if the buffer does not have a line terminator.
1164 ReadFile(ServicesFile
,
1165 ServiceDBData
+ ValidData
,
1166 sizeof( ServiceDBData
) - ValidData
,
1169 ValidData
+= ReadSize
;
1171 NextLine
= ThisLine
= ServiceDBData
;
1173 /* Find the beginning of the next line */
1174 while( NextLine
< ServiceDBData
+ ValidData
&&
1175 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1177 /* Zero and skip, so we can treat what we have as a string */
1178 if( NextLine
>= ServiceDBData
+ ValidData
)
1181 *NextLine
= 0; NextLine
++;
1183 Comment
= strchr( ThisLine
, '#' );
1184 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1186 if(DecodeServEntFromString(ThisLine
,
1191 WS2_INTERNAL_MAX_ALIAS
) &&
1192 (htons(atoi( PortNumberStr
)) == port
) &&
1193 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1196 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1199 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1200 (NextLine
- ThisLine
);
1204 /* Get rid of everything we read so far */
1205 while( NextLine
<= ServiceDBData
+ ValidData
&&
1206 isspace( *NextLine
) )
1211 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1212 ServiceDBData
+ ValidData
- NextLine
));
1214 memmove(ServiceDBData
,
1216 ServiceDBData
+ ValidData
- NextLine
);
1217 ValidData
-= NextLine
- ServiceDBData
;
1218 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1221 /* This we'll do no matter what */
1222 CloseHandle( ServicesFile
);
1226 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1227 WSASetLastError( WSANO_DATA
);
1231 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1233 /* Free previous getservbyport buffer, allocate bigger */
1234 if( p
->Getservbyport
)
1235 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1236 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1239 if( !p
->Getservbyport
)
1241 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1243 WSASetLastError( WSATRY_AGAIN
);
1246 p
->Getservbyport
->Size
= SizeNeeded
;
1249 memmove(p
->Getservbyport
->Data
,
1251 NextLine
- ThisLine
);
1253 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1254 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1255 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1256 PortNumberStr
, ProtocolStr
));
1258 for( i
= 0; Aliases
[i
]; i
++ )
1260 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1261 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1264 memcpy(p
->Getservbyport
,Aliases
,sizeof(Aliases
));
1266 /* Create the struct proper */
1267 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1268 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1269 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1270 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1272 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1274 return &p
->Getservbyport
->ServerEntry
;
1284 inet_addr(IN CONST CHAR FAR
* cp
)
1286 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1288 * cp = Pointer to string with address to convert
1290 * Binary representation of IPv4 address, or INADDR_NONE
1301 WSASetLastError(WSAEFAULT
);
1308 if (strcmp(p
, " ") == 0)
1311 for (i
= 0; i
<= 3; i
++)
1313 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1333 inet_ntoa(IN IN_ADDR in
)
1338 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1339 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1341 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1344 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1347 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1351 return (CHAR FAR
*)p
;
1360 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1362 struct addrinfo
*next
, *cur
;
1366 next
= cur
->ai_next
;
1368 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1369 if (cur
->ai_canonname
)
1370 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1371 HeapFree(GetProcessHeap(), 0, cur
);
1378 new_addrinfo(struct addrinfo
*prev
)
1380 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1382 prev
->ai_next
= ret
;
1391 getaddrinfo(const char FAR
* nodename
,
1392 const char FAR
* servname
,
1393 const struct addrinfo FAR
* hints
,
1394 struct addrinfo FAR
* FAR
* res
)
1396 struct addrinfo
*ret
= NULL
, *ai
;
1402 DNS_STATUS dns_status
;
1403 PDNS_RECORD dp
, currdns
;
1404 struct sockaddr_in
*sin
;
1408 if (nodename
== NULL
&& servname
== NULL
)
1409 return WSAHOST_NOT_FOUND
;
1411 if (!WSAINITIALIZED
)
1412 return WSANOTINITIALISED
;
1416 /* converting port number */
1417 port
= strtoul(servname
, NULL
, 10);
1418 /* service name was specified? */
1421 /* protocol was specified? */
1422 if (hints
&& hints
->ai_protocol
)
1424 pent
= getprotobynumber(hints
->ai_protocol
);
1427 proto
= pent
->p_name
;
1431 se
= getservbyname(servname
, proto
);
1433 return WSATYPE_NOT_FOUND
;
1444 /* Is it an IPv6 address? */
1445 if (strstr(nodename
, ":"))
1446 return WSAHOST_NOT_FOUND
;
1448 /* Is it an IPv4 address? */
1449 addr
= inet_addr(nodename
);
1450 if (addr
!= INADDR_NONE
)
1452 ai
= new_addrinfo(NULL
);
1453 ai
->ai_family
= PF_INET
;
1454 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1455 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1456 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1457 sin
->sin_family
= AF_INET
;
1458 sin
->sin_port
= port
;
1459 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1462 if (ai
->ai_socktype
== 0)
1463 ai
->ai_socktype
= hints
->ai_socktype
;
1464 if (ai
->ai_protocol
== 0)
1465 ai
->ai_protocol
= hints
->ai_protocol
;
1471 /* resolving host name */
1472 dns_status
= DnsQuery_A(nodename
,
1476 /* extra dns servers */ &dp
,
1479 if (dns_status
== 0)
1482 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1484 /* accept only A records */
1485 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1487 ai
= new_addrinfo(ai
);
1490 ai
->ai_family
= PF_INET
;
1491 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1492 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1493 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1494 sin
->sin_family
= AF_INET
;
1495 sin
->sin_port
= port
;
1496 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1499 if (ai
->ai_socktype
== 0)
1500 ai
->ai_socktype
= hints
->ai_socktype
;
1501 if (ai
->ai_protocol
== 0)
1502 ai
->ai_protocol
= hints
->ai_protocol
;
1505 DnsRecordListFree(dp
, DnsFreeRecordList
);
1511 ai
= new_addrinfo(NULL
);
1512 ai
->ai_family
= PF_INET
;
1513 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1514 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1515 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1516 sin
->sin_family
= AF_INET
;
1517 sin
->sin_port
= port
;
1520 if (!(hints
->ai_flags
& AI_PASSIVE
))
1522 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1523 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1524 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1525 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1527 if (ai
->ai_socktype
== 0)
1528 ai
->ai_socktype
= hints
->ai_socktype
;
1529 if (ai
->ai_protocol
== 0)
1530 ai
->ai_protocol
= hints
->ai_protocol
;
1536 return WSAHOST_NOT_FOUND
;
1538 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1541 return WSAEAFNOSUPPORT
;