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
18 #ifndef MAX_HOSTNAME_LEN
19 #define MAX_HOSTNAME_LEN 256
22 /* Name resolution APIs */
29 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress
,
30 IN DWORD dwAddressLength
,
31 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
32 OUT LPSTR lpszAddressString
,
33 IN OUT LPDWORD lpdwAddressStringLength
)
37 WSASetLastError(WSASYSCALLFAILURE
);
47 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
48 IN DWORD dwAddressLength
,
49 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
50 OUT LPWSTR lpszAddressString
,
51 IN OUT LPDWORD lpdwAddressStringLength
)
55 WSASetLastError(WSASYSCALLFAILURE
);
65 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
66 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
70 WSASetLastError(WSASYSCALLFAILURE
);
80 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
81 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
85 WSASetLastError(WSASYSCALLFAILURE
);
95 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
96 IN LPGUID lpServiceClassId
,
97 IN OUT LPDWORD lpdwBufferLength
,
98 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
102 WSASetLastError(WSASYSCALLFAILURE
);
112 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
113 IN LPGUID lpServiceClassId
,
114 IN OUT LPDWORD lpdwBufferLength
,
115 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
119 WSASetLastError(WSASYSCALLFAILURE
);
129 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
130 OUT LPSTR lpszServiceClassName
,
131 IN OUT LPDWORD lpdwBufferLength
)
135 WSASetLastError(WSASYSCALLFAILURE
);
145 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
146 OUT LPWSTR lpszServiceClassName
,
147 IN OUT LPDWORD lpdwBufferLength
)
151 WSASetLastError(WSASYSCALLFAILURE
);
161 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
165 WSASetLastError(WSASYSCALLFAILURE
);
175 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
179 WSASetLastError(WSASYSCALLFAILURE
);
189 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
190 IN DWORD dwControlFlags
,
191 OUT LPHANDLE lphLookup
)
195 WSASetLastError(WSASYSCALLFAILURE
);
205 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
206 IN DWORD dwControlFlags
,
207 OUT LPHANDLE lphLookup
)
211 WSASetLastError(WSASYSCALLFAILURE
);
221 WSALookupServiceEnd(IN HANDLE hLookup
)
225 WSASetLastError(WSASYSCALLFAILURE
);
235 WSALookupServiceNextA(IN HANDLE hLookup
,
236 IN DWORD dwControlFlags
,
237 IN OUT LPDWORD lpdwBufferLength
,
238 OUT LPWSAQUERYSETA lpqsResults
)
242 WSASetLastError(WSASYSCALLFAILURE
);
252 WSALookupServiceNextW(IN HANDLE hLookup
,
253 IN DWORD dwControlFlags
,
254 IN OUT LPDWORD lpdwBufferLength
,
255 OUT LPWSAQUERYSETW lpqsResults
)
259 WSASetLastError(WSASYSCALLFAILURE
);
269 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
273 WSASetLastError(WSASYSCALLFAILURE
);
283 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
284 IN WSAESETSERVICEOP essOperation
,
285 IN DWORD dwControlFlags
)
289 WSASetLastError(WSASYSCALLFAILURE
);
299 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
300 IN WSAESETSERVICEOP essOperation
,
301 IN DWORD dwControlFlags
)
305 WSASetLastError(WSASYSCALLFAILURE
);
315 WSAStringToAddressA(IN LPSTR AddressString
,
316 IN INT AddressFamily
,
317 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
318 OUT LPSOCKADDR lpAddress
,
319 IN OUT LPINT lpAddressLength
)
323 LPWSAPROTOCOL_INFOW lpProtoInfoW
= NULL
;
325 len
= MultiByteToWideChar(CP_ACP
,
332 szTemp
= HeapAlloc(GetProcessHeap(),
334 len
* sizeof(WCHAR
));
336 MultiByteToWideChar(CP_ACP
,
345 len
= WSAPROTOCOL_LEN
+1;
346 lpProtoInfoW
= HeapAlloc(GetProcessHeap(),
348 len
* sizeof(WCHAR
) );
352 sizeof(LPWSAPROTOCOL_INFOA
));
354 MultiByteToWideChar(CP_ACP
,
356 lpProtocolInfo
->szProtocol
,
358 lpProtoInfoW
->szProtocol
,
362 ret
= WSAStringToAddressW(szTemp
,
368 HeapFree(GetProcessHeap(),
373 HeapFree(GetProcessHeap(),
377 WSASetLastError(ret
);
388 WSAStringToAddressW(IN LPWSTR AddressString
,
389 IN INT AddressFamily
,
390 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
391 OUT LPSOCKADDR lpAddress
,
392 IN OUT LPINT lpAddressLength
)
398 SOCKADDR_IN
*sockaddr
;
400 if (!lpAddressLength
|| !lpAddress
|| !AddressString
)
402 WSASetLastError(WSAEINVAL
);
406 sockaddr
= (SOCKADDR_IN
*) lpAddress
;
408 /* Set right adress family */
409 if (lpProtocolInfo
!=NULL
)
410 sockaddr
->sin_family
= lpProtocolInfo
->iAddressFamily
;
412 else sockaddr
->sin_family
= AddressFamily
;
415 if (AddressFamily
== AF_INET
)
417 if (*lpAddressLength
< (INT
)sizeof(SOCKADDR_IN
))
419 *lpAddressLength
= sizeof(SOCKADDR_IN
);
424 // translate ip string to ip
426 /* rest sockaddr.sin_addr.s_addr
427 for we need to be sure it is zero when we come to while */
428 memset(lpAddress
,0,sizeof(SOCKADDR_IN
));
430 /* Set right adress family */
431 sockaddr
->sin_family
= AF_INET
;
433 /* Get port number */
434 pos
= wcscspn(AddressString
,L
":") + 1;
436 if (pos
< (int)wcslen(AddressString
))
437 sockaddr
->sin_port
= wcstol(&AddressString
[pos
],
442 sockaddr
->sin_port
= 0;
448 while (pos
< (int)wcslen(AddressString
))
450 inetaddr
= (inetaddr
<<8) + ((UCHAR
)wcstol(&AddressString
[pos
],
453 pos
+= wcscspn( &AddressString
[pos
],L
".") +1 ;
457 sockaddr
->sin_addr
.s_addr
= inetaddr
;
462 WSASetLastError(res
);
467 void check_hostent(struct hostent
**he
)
469 struct hostent
*new_he
;
471 WS_DbgPrint(MID_TRACE
,("*he: %x\n",*he
));
475 new_he
= HeapAlloc(GlobalHeap
,
477 sizeof(struct hostent
) + MAX_HOSTNAME_LEN
+ 1);
479 new_he
->h_name
= (PCHAR
)(new_he
+ 1);
480 new_he
->h_aliases
= 0;
481 new_he
->h_addrtype
= 0; // AF_INET
482 new_he
->h_length
= 0; // sizeof(in_addr)
483 new_he
->h_addr_list
= HeapAlloc(GlobalHeap
,
487 RtlZeroMemory(new_he
->h_addr_list
,
493 void populate_hostent(struct hostent
*he
, char* name
, DNS_A_DATA addr
)
497 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
498 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
504 if( !he
->h_aliases
) {
505 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
506 he
->h_aliases
[0] = 0;
508 he
->h_addrtype
= AF_INET
;
509 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
511 if( he
->h_addr_list
[0] )
518 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
520 MAX_HOSTNAME_LEN
+ 1);
522 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
524 RtlCopyMemory(he
->h_addr_list
[0],
525 (char*)&addr
.IpAddress
,
526 sizeof(addr
.IpAddress
));
528 he
->h_addr_list
[1] = 0;
532 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
533 void free_hostent(struct hostent
*he
)
541 next
= he
->h_aliases
[0];
542 while(next
) { HFREE(next
); next
++; }
546 next
= he
->h_addr_list
[0];
547 while(next
) { HFREE(next
); next
++; }
549 HFREE(he
->h_addr_list
);
550 HFREE(he
->h_aliases
);
555 /* WinSock 1.1 compatible name resolution APIs */
562 gethostbyaddr(IN CONST CHAR FAR
* addr
,
568 return (LPHOSTENT
)NULL
;
572 Assumes rfc 1123 - adam *
574 addr[0] = inet_addr(name);
575 strcpy( hostname, name );
576 if(addr[0] == 0xffffffff) return NULL;
577 he.h_addr_list = (void *)addr;
578 he.h_name = hostname;
580 he.h_addrtype = AF_INET;
581 he.h_length = sizeof(addr);
585 From the MSDN Platform SDK: Windows Sockets 2
586 "The gethostbyname function cannot resolve IP address strings passed to it.
587 Such a request is treated exactly as if an unknown host name were passed."
590 Defferring to the the documented behaviour, rather than the unix behaviour
591 What if the hostname is in the HOSTS file? see getservbyname
596 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
597 /* see ws2_32.h, winsock2.h*/
598 /*getnetworkparameters - iphlp api */
602 servent -- w32api/include/winsock2.h
603 PWINSOCK_THREAD_BLOCK -- ws2_32.h
604 dllmain.c -- threadlocal memory allocation / deallocation
609 /* lib/adns/src/adns.h XXX */
619 #define h_addr h_addr_list[0]
629 struct hostent defined in w32api/include/winsock2.h
632 void free_servent(struct servent
* s
)
636 next
= s
->s_aliases
[0];
637 while(next
) { HFREE(next
); next
++; }
647 gethostbyname(IN CONST CHAR FAR
* name
)
656 typedef enum addr_type addr_type
;
660 DNS_STATUS dns_status
= {0};
661 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
663 PWINSOCK_THREAD_BLOCK p
;
667 p
= NtCurrentTeb()->WinSockData
;
671 WSASetLastError( WSANOTINITIALISED
);
675 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
677 /* Hostname NULL - behave like gethostname */
680 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
686 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
690 /* Is it an IPv6 address? */
691 found
= strstr(name
, ":");
698 /* Is it an IPv4 address? */
699 if (!isalpha(name
[0]))
705 addr
= GH_RFC1123_DNS
;
707 /* Broken out in case we want to get fancy later */
712 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
717 WSASetLastError(WSAEFAULT
);
721 /* Note: If passed an IP address, MSDN says that gethostbyname()
722 treats it as an unknown host.
723 This is different from the unix implementation. Use inet_addr()
727 /* DNS_TYPE_A: include/WinDNS.h */
728 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
729 dns_status
= DnsQuery_A(name
,
733 /* extra dns servers */ &dp
,
738 //ASSERT(dp->wType == DNS_TYPE_A);
739 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
742 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
745 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
751 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
752 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
753 populate_hostent(p
->Hostent
, (PCHAR
)curr
->pName
, curr
->Data
.A
);
754 DnsRecordListFree(dp
, DnsFreeRecordList
);
759 DnsRecordListFree(dp
, DnsFreeRecordList
);
763 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
765 WSASetLastError(WSAHOST_NOT_FOUND
);
771 WSASetLastError(WSANO_RECOVERY
);
776 WSASetLastError(WSANO_RECOVERY
);
785 gethostname(OUT CHAR FAR
* name
,
788 DWORD size
= namelen
;
790 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
795 WSASetLastError(WSAEFAULT
);
800 name
[namelen
-1] = '\0';
807 * XXX arty -- Partial implementation pending a better one. This one will
808 * do for normal purposes.#include <ws2_32.h>
810 * Return the address of a static LPPROTOENT corresponding to the named
811 * protocol. These structs aren't very interesting, so I'm not too ashamed
812 * to have this function work on builtins for now.
817 static CHAR
*no_aliases
= 0;
818 static PROTOENT protocols
[] =
820 {"icmp",&no_aliases
, IPPROTO_ICMP
},
821 {"tcp", &no_aliases
, IPPROTO_TCP
},
822 {"udp", &no_aliases
, IPPROTO_UDP
},
828 getprotobyname(IN CONST CHAR FAR
* name
)
831 for (i
= 0; protocols
[i
].p_name
; i
++)
833 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
834 return &protocols
[i
];
844 getprotobynumber(IN INT number
)
847 for (i
= 0; protocols
[i
].p_name
; i
++)
849 if (protocols
[i
].p_proto
== number
)
850 return &protocols
[i
];
855 #define SKIPWS(ptr,act) \
856 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
857 #define SKIPANDMARKSTR(ptr,act) \
858 {while(*ptr && !isspace(*ptr)) ptr++; \
859 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
863 DecodeServEntFromString(IN PCHAR ServiceString
,
864 OUT PCHAR
*ServiceName
,
865 OUT PCHAR
*PortNumberStr
,
866 OUT PCHAR
*ProtocolStr
,
872 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
874 SKIPWS(ServiceString
, return FALSE
);
875 *ServiceName
= ServiceString
;
876 SKIPANDMARKSTR(ServiceString
, return FALSE
);
877 SKIPWS(ServiceString
, return FALSE
);
878 *PortNumberStr
= ServiceString
;
879 SKIPANDMARKSTR(ServiceString
, ;);
881 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
883 SKIPWS(ServiceString
, break);
886 SKIPANDMARKSTR(ServiceString
, ;);
887 if( strlen(ServiceString
) )
889 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
890 *Aliases
++ = ServiceString
;
897 *ProtocolStr
= strchr(*PortNumberStr
,'/');
898 if( !*ProtocolStr
) return FALSE
;
899 **ProtocolStr
= 0; (*ProtocolStr
)++;
901 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
902 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
908 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
915 getservbyname(IN CONST CHAR FAR
* name
,
916 IN CONST CHAR FAR
* proto
)
920 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
921 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
922 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
923 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
924 ProtocolStr
= 0, Comment
= 0;
925 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
926 UINT i
,SizeNeeded
= 0,
927 SystemDirSize
= sizeof(ServiceDBData
) - 1;
928 DWORD ReadSize
= 0, ValidData
= 0;
929 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
933 WSASetLastError( WSANOTINITIALISED
);
939 WSASetLastError( WSANO_RECOVERY
);
943 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
945 WSASetLastError( WSANO_RECOVERY
);
946 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
947 return NULL
; /* Can't get system directory */
950 strncat(SystemDirectory
,
951 ServicesFileLocation
,
954 ServicesFile
= CreateFileA(SystemDirectory
,
959 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
962 if( ServicesFile
== INVALID_HANDLE_VALUE
)
964 WSASetLastError( WSANO_RECOVERY
);
968 /* Scan the services file ...
970 * We will read up to BUFSIZ bytes per pass, until the buffer does not
971 * contain a full line, then we will try to read more.
973 * We fall from the loop if the buffer does not have a line terminator.
978 ReadFile(ServicesFile
,
979 ServiceDBData
+ ValidData
,
980 sizeof( ServiceDBData
) - ValidData
,
984 ValidData
+= ReadSize
;
986 NextLine
= ThisLine
= ServiceDBData
;
988 /* Find the beginning of the next line */
989 while(NextLine
< ServiceDBData
+ ValidData
&&
990 *NextLine
!= '\r' && *NextLine
!= '\n' )
995 /* Zero and skip, so we can treat what we have as a string */
996 if( NextLine
>= ServiceDBData
+ ValidData
)
999 *NextLine
= 0; NextLine
++;
1001 Comment
= strchr( ThisLine
, '#' );
1002 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1004 if(DecodeServEntFromString(ThisLine
,
1009 WS2_INTERNAL_MAX_ALIAS
) &&
1010 !strcmp( ServiceName
, name
) &&
1011 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1014 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1016 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1017 (NextLine
- ThisLine
);
1021 /* Get rid of everything we read so far */
1022 while( NextLine
<= ServiceDBData
+ ValidData
&&
1023 isspace( *NextLine
) )
1028 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1029 ServiceDBData
+ ValidData
- NextLine
));
1031 memmove(ServiceDBData
,
1033 ServiceDBData
+ ValidData
- NextLine
);
1034 ValidData
-= NextLine
- ServiceDBData
;
1035 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1038 /* This we'll do no matter what */
1039 CloseHandle( ServicesFile
);
1043 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1044 WSASetLastError( WSANO_DATA
);
1048 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1050 /* Free previous getservbyname buffer, allocate bigger */
1051 if( p
->Getservbyname
)
1052 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1053 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1054 if( !p
->Getservbyname
)
1056 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1058 WSASetLastError( WSATRY_AGAIN
);
1061 p
->Getservbyname
->Size
= SizeNeeded
;
1065 memmove(p
->Getservbyname
->Data
,
1067 NextLine
- ThisLine
);
1069 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1070 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1071 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1075 for( i
= 0; Aliases
[i
]; i
++ )
1077 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1078 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1081 memcpy(p
->Getservbyname
,
1085 /* Create the struct proper */
1086 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1087 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1088 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1089 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1091 return &p
->Getservbyname
->ServerEntry
;
1100 getservbyport(IN INT port
,
1101 IN CONST CHAR FAR
* proto
)
1104 HANDLE ServicesFile
;
1105 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1106 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1107 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1108 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1109 ProtocolStr
= 0, Comment
= 0;
1110 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1111 UINT i
,SizeNeeded
= 0,
1112 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1113 DWORD ReadSize
= 0, ValidData
= 0;
1114 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1118 WSASetLastError( WSANOTINITIALISED
);
1124 WSASetLastError( WSANO_RECOVERY
);
1128 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1130 WSASetLastError( WSANO_RECOVERY
);
1131 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1132 return NULL
; /* Can't get system directory */
1135 strncat(SystemDirectory
,
1136 ServicesFileLocation
,
1139 ServicesFile
= CreateFileA(SystemDirectory
,
1144 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1147 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1149 WSASetLastError( WSANO_RECOVERY
);
1153 /* Scan the services file ...
1155 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1156 * contain a full line, then we will try to read more.
1158 * We fall from the loop if the buffer does not have a line terminator.
1163 ReadFile(ServicesFile
,
1164 ServiceDBData
+ ValidData
,
1165 sizeof( ServiceDBData
) - ValidData
,
1168 ValidData
+= ReadSize
;
1170 NextLine
= ThisLine
= ServiceDBData
;
1172 /* Find the beginning of the next line */
1173 while( NextLine
< ServiceDBData
+ ValidData
&&
1174 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1176 /* Zero and skip, so we can treat what we have as a string */
1177 if( NextLine
>= ServiceDBData
+ ValidData
)
1180 *NextLine
= 0; NextLine
++;
1182 Comment
= strchr( ThisLine
, '#' );
1183 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1185 if(DecodeServEntFromString(ThisLine
,
1190 WS2_INTERNAL_MAX_ALIAS
) &&
1191 (htons(atoi( PortNumberStr
)) == port
) &&
1192 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1195 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1198 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1199 (NextLine
- ThisLine
);
1203 /* Get rid of everything we read so far */
1204 while( NextLine
<= ServiceDBData
+ ValidData
&&
1205 isspace( *NextLine
) )
1210 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1211 ServiceDBData
+ ValidData
- NextLine
));
1213 memmove(ServiceDBData
,
1215 ServiceDBData
+ ValidData
- NextLine
);
1216 ValidData
-= NextLine
- ServiceDBData
;
1217 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1220 /* This we'll do no matter what */
1221 CloseHandle( ServicesFile
);
1225 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1226 WSASetLastError( WSANO_DATA
);
1230 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1232 /* Free previous getservbyport buffer, allocate bigger */
1233 if( p
->Getservbyport
)
1234 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1235 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1238 if( !p
->Getservbyport
)
1240 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1242 WSASetLastError( WSATRY_AGAIN
);
1245 p
->Getservbyport
->Size
= SizeNeeded
;
1248 memmove(p
->Getservbyport
->Data
,
1250 NextLine
- ThisLine
);
1252 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1253 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1254 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1255 PortNumberStr
, ProtocolStr
));
1257 for( i
= 0; Aliases
[i
]; i
++ )
1259 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1260 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1263 memcpy(p
->Getservbyport
,Aliases
,sizeof(Aliases
));
1265 /* Create the struct proper */
1266 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1267 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1268 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1269 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1271 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1273 return &p
->Getservbyport
->ServerEntry
;
1283 inet_addr(IN CONST CHAR FAR
* cp
)
1285 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1287 * cp = Pointer to string with address to convert
1289 * Binary representation of IPv4 address, or INADDR_NONE
1300 WSASetLastError(WSAEFAULT
);
1307 if (strcmp(p
, " ") == 0)
1310 for (i
= 0; i
<= 3; i
++)
1312 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1332 inet_ntoa(IN IN_ADDR in
)
1337 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1338 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1340 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1343 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1346 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1350 return (CHAR FAR
*)p
;
1359 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1361 struct addrinfo
*next
, *cur
;
1365 next
= cur
->ai_next
;
1367 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1368 if (cur
->ai_canonname
)
1369 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1370 HeapFree(GetProcessHeap(), 0, cur
);
1377 new_addrinfo(struct addrinfo
*prev
)
1379 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1381 prev
->ai_next
= ret
;
1390 getaddrinfo(const char FAR
* nodename
,
1391 const char FAR
* servname
,
1392 const struct addrinfo FAR
* hints
,
1393 struct addrinfo FAR
* FAR
* res
)
1395 struct addrinfo
*ret
= NULL
, *ai
;
1401 DNS_STATUS dns_status
;
1402 PDNS_RECORD dp
, currdns
;
1403 struct sockaddr_in
*sin
;
1407 if (nodename
== NULL
&& servname
== NULL
)
1408 return WSAHOST_NOT_FOUND
;
1410 if (!WSAINITIALIZED
)
1411 return WSANOTINITIALISED
;
1415 /* converting port number */
1416 port
= strtoul(servname
, NULL
, 10);
1417 /* service name was specified? */
1420 /* protocol was specified? */
1421 if (hints
&& hints
->ai_protocol
)
1423 pent
= getprotobynumber(hints
->ai_protocol
);
1426 proto
= pent
->p_name
;
1430 se
= getservbyname(servname
, proto
);
1432 return WSATYPE_NOT_FOUND
;
1443 /* Is it an IPv6 address? */
1444 if (strstr(nodename
, ":"))
1445 return WSAHOST_NOT_FOUND
;
1447 /* Is it an IPv4 address? */
1448 addr
= inet_addr(nodename
);
1449 if (addr
!= INADDR_NONE
)
1451 ai
= new_addrinfo(NULL
);
1452 ai
->ai_family
= PF_INET
;
1453 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1454 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1455 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1456 sin
->sin_family
= AF_INET
;
1457 sin
->sin_port
= port
;
1458 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1461 if (ai
->ai_socktype
== 0)
1462 ai
->ai_socktype
= hints
->ai_socktype
;
1463 if (ai
->ai_protocol
== 0)
1464 ai
->ai_protocol
= hints
->ai_protocol
;
1470 /* resolving host name */
1471 dns_status
= DnsQuery_A(nodename
,
1475 /* extra dns servers */ &dp
,
1478 if (dns_status
== 0)
1481 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1483 /* accept only A records */
1484 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1486 ai
= new_addrinfo(ai
);
1489 ai
->ai_family
= PF_INET
;
1490 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1491 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1492 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1493 sin
->sin_family
= AF_INET
;
1494 sin
->sin_port
= port
;
1495 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1498 if (ai
->ai_socktype
== 0)
1499 ai
->ai_socktype
= hints
->ai_socktype
;
1500 if (ai
->ai_protocol
== 0)
1501 ai
->ai_protocol
= hints
->ai_protocol
;
1504 DnsRecordListFree(dp
, DnsFreeRecordList
);
1510 ai
= new_addrinfo(NULL
);
1511 ai
->ai_family
= PF_INET
;
1512 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1513 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1514 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1515 sin
->sin_family
= AF_INET
;
1516 sin
->sin_port
= port
;
1519 if (!(hints
->ai_flags
& AI_PASSIVE
))
1521 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1522 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1523 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1524 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1526 if (ai
->ai_socktype
== 0)
1527 ai
->ai_socktype
= hints
->ai_socktype
;
1528 if (ai
->ai_protocol
== 0)
1529 ai
->ai_protocol
= hints
->ai_protocol
;
1535 return WSAHOST_NOT_FOUND
;
1537 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1540 return WSAEAFNOSUPPORT
;