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
17 #ifndef MAX_HOSTNAME_LEN
18 #define MAX_HOSTNAME_LEN 256
21 /* Name resolution APIs */
28 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress
,
29 IN DWORD dwAddressLength
,
30 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
31 OUT LPSTR lpszAddressString
,
32 IN OUT LPDWORD lpdwAddressStringLength
)
35 CHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
38 if (!lpsaAddress
) return SOCKET_ERROR
;
39 if (!lpszAddressString
|| !lpdwAddressStringLength
) return SOCKET_ERROR
;
41 switch(lpsaAddress
->sa_family
)
44 if (dwAddressLength
< sizeof(SOCKADDR_IN
)) return SOCKET_ERROR
;
45 sprintf( buffer
, "%u.%u.%u.%u:%u",
46 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 24 & 0xff),
47 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 16 & 0xff),
48 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 8 & 0xff),
49 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) & 0xff),
50 ntohs( ((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) );
52 p
= strchr( buffer
, ':' );
53 if (!((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) *p
= 0;
56 WSASetLastError(WSAEINVAL
);
60 size
= strlen( buffer
) + 1;
62 if (*lpdwAddressStringLength
< size
)
64 *lpdwAddressStringLength
= size
;
65 WSASetLastError(WSAEFAULT
);
69 *lpdwAddressStringLength
= size
;
70 strcpy( lpszAddressString
, buffer
);
80 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
81 IN DWORD dwAddressLength
,
82 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
83 OUT LPWSTR lpszAddressString
,
84 IN OUT LPDWORD lpdwAddressStringLength
)
88 WCHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
91 size
= *lpdwAddressStringLength
;
92 ret
= WSAAddressToStringA(lpsaAddress
, dwAddressLength
, NULL
, bufAddr
, &size
);
96 MultiByteToWideChar( CP_ACP
, 0, bufAddr
, size
, buffer
, sizeof( buffer
)/sizeof(WCHAR
));
98 if (*lpdwAddressStringLength
< size
)
100 *lpdwAddressStringLength
= size
;
101 WSASetLastError(WSAEFAULT
);
105 *lpdwAddressStringLength
= size
;
106 lstrcpyW( lpszAddressString
, buffer
);
116 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
117 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
121 WSASetLastError(WSASYSCALLFAILURE
);
131 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
132 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
136 WSASetLastError(WSASYSCALLFAILURE
);
146 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
147 IN LPGUID lpServiceClassId
,
148 IN OUT LPDWORD lpdwBufferLength
,
149 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
153 WSASetLastError(WSASYSCALLFAILURE
);
163 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
164 IN LPGUID lpServiceClassId
,
165 IN OUT LPDWORD lpdwBufferLength
,
166 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
170 WSASetLastError(WSASYSCALLFAILURE
);
180 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
181 OUT LPSTR lpszServiceClassName
,
182 IN OUT LPDWORD lpdwBufferLength
)
186 WSASetLastError(WSASYSCALLFAILURE
);
196 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
197 OUT LPWSTR lpszServiceClassName
,
198 IN OUT LPDWORD lpdwBufferLength
)
202 WSASetLastError(WSASYSCALLFAILURE
);
212 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
216 WSASetLastError(WSASYSCALLFAILURE
);
226 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
230 WSASetLastError(WSASYSCALLFAILURE
);
240 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
241 IN DWORD dwControlFlags
,
242 OUT LPHANDLE lphLookup
)
246 WSASetLastError(WSASYSCALLFAILURE
);
256 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
257 IN DWORD dwControlFlags
,
258 OUT LPHANDLE lphLookup
)
262 WSASetLastError(WSASYSCALLFAILURE
);
272 WSALookupServiceEnd(IN HANDLE hLookup
)
276 WSASetLastError(WSASYSCALLFAILURE
);
286 WSALookupServiceNextA(IN HANDLE hLookup
,
287 IN DWORD dwControlFlags
,
288 IN OUT LPDWORD lpdwBufferLength
,
289 OUT LPWSAQUERYSETA lpqsResults
)
293 WSASetLastError(WSASYSCALLFAILURE
);
303 WSALookupServiceNextW(IN HANDLE hLookup
,
304 IN DWORD dwControlFlags
,
305 IN OUT LPDWORD lpdwBufferLength
,
306 OUT LPWSAQUERYSETW lpqsResults
)
310 WSASetLastError(WSASYSCALLFAILURE
);
320 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
324 WSASetLastError(WSASYSCALLFAILURE
);
334 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
335 IN WSAESETSERVICEOP essOperation
,
336 IN DWORD dwControlFlags
)
340 WSASetLastError(WSASYSCALLFAILURE
);
350 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
351 IN WSAESETSERVICEOP essOperation
,
352 IN DWORD dwControlFlags
)
356 WSASetLastError(WSASYSCALLFAILURE
);
366 WSAStringToAddressA(IN LPSTR AddressString
,
367 IN INT AddressFamily
,
368 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
369 OUT LPSOCKADDR lpAddress
,
370 IN OUT LPINT lpAddressLength
)
374 WSAPROTOCOL_INFOW ProtoInfoW
;
376 len
= MultiByteToWideChar(CP_ACP
,
383 szTemp
= HeapAlloc(GetProcessHeap(),
385 len
* sizeof(WCHAR
));
387 MultiByteToWideChar(CP_ACP
,
398 FIELD_OFFSET(WSAPROTOCOL_INFOA
, szProtocol
));
400 MultiByteToWideChar(CP_ACP
,
402 lpProtocolInfo
->szProtocol
,
404 ProtoInfoW
.szProtocol
,
405 WSAPROTOCOL_LEN
+ 1);
408 ret
= WSAStringToAddressW(szTemp
,
414 HeapFree(GetProcessHeap(),
418 WSASetLastError(ret
);
429 WSAStringToAddressW(IN LPWSTR AddressString
,
430 IN INT AddressFamily
,
431 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
432 OUT LPSOCKADDR lpAddress
,
433 IN OUT LPINT lpAddressLength
)
439 SOCKADDR_IN
*sockaddr
;
441 if (!lpAddressLength
|| !lpAddress
|| !AddressString
)
443 WSASetLastError(WSAEINVAL
);
447 sockaddr
= (SOCKADDR_IN
*) lpAddress
;
449 /* Set right adress family */
450 if (lpProtocolInfo
!=NULL
)
451 sockaddr
->sin_family
= lpProtocolInfo
->iAddressFamily
;
453 sockaddr
->sin_family
= AddressFamily
;
456 if (AddressFamily
== AF_INET
)
458 if (*lpAddressLength
< (INT
)sizeof(SOCKADDR_IN
))
460 *lpAddressLength
= sizeof(SOCKADDR_IN
);
465 // translate ip string to ip
467 /* rest sockaddr.sin_addr.s_addr
468 for we need to be sure it is zero when we come to while */
469 memset(lpAddress
,0,sizeof(SOCKADDR_IN
));
471 /* Set right adress family */
472 sockaddr
->sin_family
= AF_INET
;
474 /* Get port number */
475 pos
= wcscspn(AddressString
,L
":") + 1;
477 if (pos
< (int)wcslen(AddressString
))
478 sockaddr
->sin_port
= wcstol(&AddressString
[pos
],
483 sockaddr
->sin_port
= 0;
489 while (pos
< (int)wcslen(AddressString
))
491 inetaddr
= (inetaddr
<<8) + ((UCHAR
)wcstol(&AddressString
[pos
],
494 pos
+= wcscspn( &AddressString
[pos
],L
".") +1 ;
498 sockaddr
->sin_addr
.s_addr
= inetaddr
;
503 WSASetLastError(res
);
508 void check_hostent(struct hostent
**he
)
510 struct hostent
*new_he
;
512 WS_DbgPrint(MID_TRACE
,("*he: %x\n",*he
));
516 new_he
= HeapAlloc(GlobalHeap
,
518 sizeof(struct hostent
) + MAX_HOSTNAME_LEN
+ 1);
520 new_he
->h_name
= (PCHAR
)(new_he
+ 1);
521 new_he
->h_aliases
= NULL
;
522 new_he
->h_addrtype
= 0; // AF_INET
523 new_he
->h_length
= 0; // sizeof(in_addr)
524 new_he
->h_addr_list
= HeapAlloc(GlobalHeap
,
532 void populate_hostent(struct hostent
*he
, char* name
, IP4_ADDRESS addr
)
536 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
537 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
543 if( !he
->h_aliases
) {
544 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
545 he
->h_aliases
[0] = NULL
;
547 he
->h_addrtype
= AF_INET
;
548 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
550 if( he
->h_addr_list
[0] )
557 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
559 MAX_HOSTNAME_LEN
+ 1);
561 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
563 RtlCopyMemory(he
->h_addr_list
[0],
567 he
->h_addr_list
[1] = NULL
;
570 void free_hostent(struct hostent
*he
)
577 HeapFree(GlobalHeap
, 0, he
->h_name
);
580 for (i
= 0; he
->h_aliases
[i
]; i
++)
581 HeapFree(GlobalHeap
, 0, he
->h_aliases
[i
]);
582 HeapFree(GlobalHeap
, 0, he
->h_aliases
);
586 for (i
= 0; he
->h_addr_list
[i
]; i
++)
587 HeapFree(GlobalHeap
, 0, he
->h_addr_list
[i
]);
588 HeapFree(GlobalHeap
, 0, he
->h_addr_list
);
590 HeapFree(GlobalHeap
, 0, he
);
594 /* WinSock 1.1 compatible name resolution APIs */
601 gethostbyaddr(IN CONST CHAR FAR
* addr
,
607 return (LPHOSTENT
)NULL
;
611 Assumes rfc 1123 - adam *
613 addr[0] = inet_addr(name);
614 strcpy( hostname, name );
615 if(addr[0] == 0xffffffff) return NULL;
616 he.h_addr_list = (void *)addr;
617 he.h_name = hostname;
619 he.h_addrtype = AF_INET;
620 he.h_length = sizeof(addr);
624 From the MSDN Platform SDK: Windows Sockets 2
625 "The gethostbyname function cannot resolve IP address strings passed to it.
626 Such a request is treated exactly as if an unknown host name were passed."
629 Defferring to the the documented behaviour, rather than the unix behaviour
630 What if the hostname is in the HOSTS file? see getservbyname
635 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
636 /* see ws2_32.h, winsock2.h*/
637 /*getnetworkparameters - iphlp api */
641 servent -- w32api/include/winsock2.h
642 PWINSOCK_THREAD_BLOCK -- ws2_32.h
643 dllmain.c -- threadlocal memory allocation / deallocation
648 /* lib/adns/src/adns.h XXX */
658 #define h_addr h_addr_list[0]
668 struct hostent defined in w32api/include/winsock2.h
671 void free_servent(struct servent
* s
)
678 HeapFree(GlobalHeap
, 0, s
->s_name
);
681 for (i
= 0; s
->s_aliases
[i
]; i
++)
682 HeapFree(GlobalHeap
, 0, s
->s_aliases
[i
]);
683 HeapFree(GlobalHeap
, 0, s
->s_aliases
);
686 HeapFree(GlobalHeap
, 0, s
->s_proto
);
687 HeapFree(GlobalHeap
, 0, s
);
691 /* This function is far from perfect but it works enough */
694 FindEntryInHosts(IN CONST CHAR FAR
* name
)
698 CHAR HostsDBData
[BUFSIZ
] = { 0 };
699 PCHAR SystemDirectory
= HostsDBData
;
700 PCHAR HostsLocation
= "\\drivers\\etc\\hosts";
701 PCHAR AddressStr
, DnsName
= NULL
, AddrTerm
, NameSt
, NextLine
, ThisLine
, Comment
;
702 UINT SystemDirSize
= sizeof(HostsDBData
) - 1, ValidData
= 0;
705 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
707 /* We assume that the parameters are valid */
709 if (!GetSystemDirectoryA(SystemDirectory
, SystemDirSize
))
711 WSASetLastError(WSANO_RECOVERY
);
712 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
713 return NULL
; /* Can't get system directory */
716 strncat(SystemDirectory
,
720 HostsFile
= CreateFileA(SystemDirectory
,
725 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
727 if (HostsFile
== INVALID_HANDLE_VALUE
)
729 WSASetLastError(WSANO_RECOVERY
);
735 HostsDBData
+ ValidData
,
736 sizeof(HostsDBData
) - ValidData
,
740 ValidData
+= ReadSize
;
742 NextLine
= ThisLine
= HostsDBData
;
744 /* Find the beginning of the next line */
745 while(NextLine
< HostsDBData
+ ValidData
&&
746 *NextLine
!= '\r' && *NextLine
!= '\n' )
751 /* Zero and skip, so we can treat what we have as a string */
752 if( NextLine
> HostsDBData
+ ValidData
)
755 *NextLine
= 0; NextLine
++;
757 Comment
= strchr( ThisLine
, '#' );
758 if( Comment
) *Comment
= 0; /* Terminate at comment start */
760 AddressStr
= ThisLine
;
761 /* Find the first space separating the IP address from the DNS name */
762 AddrTerm
= strchr(ThisLine
, ' ');
765 /* Terminate the address string */
768 /* Find the last space before the DNS name */
769 NameSt
= strrchr(ThisLine
, ' ');
771 /* If there is only one space (the one we removed above), then just use the address terminator */
775 /* Move from the space to the first character of the DNS name */
780 if (!strcmp(name
, DnsName
))
787 /* Get rid of everything we read so far */
788 while( NextLine
<= HostsDBData
+ ValidData
&&
794 if (HostsDBData
+ ValidData
- NextLine
<= 0)
797 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
798 HostsDBData
+ ValidData
- NextLine
));
802 HostsDBData
+ ValidData
- NextLine
);
803 ValidData
-= NextLine
- HostsDBData
;
804 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
807 CloseHandle(HostsFile
);
811 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
812 WSASetLastError(WSANO_DATA
);
816 if (strstr(AddressStr
, ":"))
818 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
819 WSASetLastError(WSAEINVAL
);
823 Address
= inet_addr(AddressStr
);
824 if (Address
== INADDR_NONE
)
826 WSASetLastError(WSAEINVAL
);
830 populate_hostent(p
->Hostent
, DnsName
, Address
);
837 gethostbyname(IN CONST CHAR FAR
* name
)
846 typedef enum addr_type addr_type
;
850 DNS_STATUS dns_status
= {0};
851 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
853 PWINSOCK_THREAD_BLOCK p
;
858 p
= NtCurrentTeb()->WinSockData
;
862 WSASetLastError( WSANOTINITIALISED
);
866 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
868 /* Hostname NULL - behave like gethostname */
871 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
874 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
880 /* Is it an IPv6 address? */
881 found
= strstr(name
, ":");
888 /* Is it an IPv4 address? */
889 if (!isalpha(name
[0]))
895 addr
= GH_RFC1123_DNS
;
897 /* Broken out in case we want to get fancy later */
902 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
907 WSASetLastError(WSAEFAULT
);
911 /* Note: If passed an IP address, MSDN says that gethostbyname()
912 treats it as an unknown host.
913 This is different from the unix implementation. Use inet_addr()
917 /* DNS_TYPE_A: include/WinDNS.h */
918 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
920 /* Look for the DNS name in the hosts file */
921 Hostent
= FindEntryInHosts(name
);
925 dns_status
= DnsQuery_A(name
,
929 /* extra dns servers */ &dp
,
934 //ASSERT(dp->wType == DNS_TYPE_A);
935 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
938 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
941 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
947 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
948 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
949 populate_hostent(p
->Hostent
,
951 curr
->Data
.A
.IpAddress
);
952 DnsRecordListFree(dp
, DnsFreeRecordList
);
957 DnsRecordListFree(dp
, DnsFreeRecordList
);
961 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
963 WSASetLastError(WSAHOST_NOT_FOUND
);
969 WSASetLastError(WSANO_RECOVERY
);
974 WSASetLastError(WSANO_RECOVERY
);
983 gethostname(OUT CHAR FAR
* name
,
986 DWORD size
= namelen
;
988 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
993 WSASetLastError(WSAEFAULT
);
998 name
[namelen
-1] = '\0';
1005 * XXX arty -- Partial implementation pending a better one. This one will
1006 * do for normal purposes.#include <ws2_32.h>
1008 * Return the address of a static LPPROTOENT corresponding to the named
1009 * protocol. These structs aren't very interesting, so I'm not too ashamed
1010 * to have this function work on builtins for now.
1015 static CHAR
*no_aliases
= 0;
1016 static PROTOENT protocols
[] =
1018 {"icmp",&no_aliases
, IPPROTO_ICMP
},
1019 {"tcp", &no_aliases
, IPPROTO_TCP
},
1020 {"udp", &no_aliases
, IPPROTO_UDP
},
1026 getprotobyname(IN CONST CHAR FAR
* name
)
1029 for (i
= 0; protocols
[i
].p_name
; i
++)
1031 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
1032 return &protocols
[i
];
1042 getprotobynumber(IN INT number
)
1045 for (i
= 0; protocols
[i
].p_name
; i
++)
1047 if (protocols
[i
].p_proto
== number
)
1048 return &protocols
[i
];
1053 #define SKIPWS(ptr,act) \
1054 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1055 #define SKIPANDMARKSTR(ptr,act) \
1056 {while(*ptr && !isspace(*ptr)) ptr++; \
1057 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1061 DecodeServEntFromString(IN PCHAR ServiceString
,
1062 OUT PCHAR
*ServiceName
,
1063 OUT PCHAR
*PortNumberStr
,
1064 OUT PCHAR
*ProtocolStr
,
1070 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
1072 SKIPWS(ServiceString
, return FALSE
);
1073 *ServiceName
= ServiceString
;
1074 SKIPANDMARKSTR(ServiceString
, return FALSE
);
1075 SKIPWS(ServiceString
, return FALSE
);
1076 *PortNumberStr
= ServiceString
;
1077 SKIPANDMARKSTR(ServiceString
, ;);
1079 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
1081 SKIPWS(ServiceString
, break);
1082 if( *ServiceString
)
1084 SKIPANDMARKSTR(ServiceString
, ;);
1085 if( strlen(ServiceString
) )
1087 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
1088 *Aliases
++ = ServiceString
;
1095 *ProtocolStr
= strchr(*PortNumberStr
,'/');
1096 if( !*ProtocolStr
) return FALSE
;
1097 **ProtocolStr
= 0; (*ProtocolStr
)++;
1099 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
1100 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
1106 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1113 getservbyname(IN CONST CHAR FAR
* name
,
1114 IN CONST CHAR FAR
* proto
)
1117 HANDLE ServicesFile
;
1118 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1119 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1120 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1121 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1122 ProtocolStr
= 0, Comment
= 0, EndValid
;
1123 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1124 UINT i
,SizeNeeded
= 0,
1125 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1127 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1131 WSASetLastError( WSANOTINITIALISED
);
1137 WSASetLastError( WSANO_RECOVERY
);
1141 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1143 WSASetLastError( WSANO_RECOVERY
);
1144 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1145 return NULL
; /* Can't get system directory */
1148 strncat(SystemDirectory
,
1149 ServicesFileLocation
,
1152 ServicesFile
= CreateFileA(SystemDirectory
,
1157 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1160 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1162 WSASetLastError( WSANO_RECOVERY
);
1166 /* Scan the services file ...
1168 * We will be share the buffer on the lines. If the line does not fit in
1169 * the buffer, then moving it to the beginning of the buffer and read
1170 * the remnants of line from file.
1174 ReadFile(ServicesFile
,
1176 sizeof( ServiceDBData
) - 1,
1178 ThisLine
= NextLine
= ServiceDBData
;
1179 EndValid
= ServiceDBData
+ ReadSize
;
1180 ServiceDBData
[sizeof(ServiceDBData
) - 1] = '\0';
1184 for(; *NextLine
!= '\r' && *NextLine
!= '\n'; NextLine
++)
1186 if(NextLine
== EndValid
)
1188 int LineLen
= NextLine
- ThisLine
;
1190 if(ThisLine
== ServiceDBData
)
1192 WS_DbgPrint(MIN_TRACE
,("Line too long"));
1193 WSASetLastError( WSANO_RECOVERY
);
1197 memmove(ServiceDBData
, ThisLine
, LineLen
);
1199 ReadFile(ServicesFile
, ServiceDBData
+ LineLen
,
1200 sizeof( ServiceDBData
)-1 - LineLen
,
1203 EndValid
= ServiceDBData
+ LineLen
+ ReadSize
;
1204 NextLine
= ServiceDBData
+ LineLen
;
1205 ThisLine
= ServiceDBData
;
1207 if(!ReadSize
) break;
1212 Comment
= strchr( ThisLine
, '#' );
1213 if( Comment
) *Comment
= '\0'; /* Terminate at comment start */
1215 if(DecodeServEntFromString(ThisLine
,
1220 WS2_INTERNAL_MAX_ALIAS
) &&
1221 !strcmp( ServiceName
, name
) &&
1222 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1225 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1227 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1228 (NextLine
- ThisLine
);
1232 ThisLine
= NextLine
;
1235 /* This we'll do no matter what */
1236 CloseHandle( ServicesFile
);
1240 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1241 WSASetLastError( WSANO_DATA
);
1245 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1247 /* Free previous getservbyname buffer, allocate bigger */
1248 if( p
->Getservbyname
)
1249 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1250 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1251 if( !p
->Getservbyname
)
1253 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1255 WSASetLastError( WSATRY_AGAIN
);
1258 p
->Getservbyname
->Size
= SizeNeeded
;
1262 memmove(p
->Getservbyname
->Data
,
1264 NextLine
- ThisLine
);
1266 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1267 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1268 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1272 for( i
= 0; Aliases
[i
]; i
++ )
1274 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1275 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1278 memcpy(p
->Getservbyname
->Aliases
,
1282 /* Create the struct proper */
1283 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1284 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1285 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1286 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1288 return &p
->Getservbyname
->ServerEntry
;
1297 getservbyport(IN INT port
,
1298 IN CONST CHAR FAR
* proto
)
1301 HANDLE ServicesFile
;
1302 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1303 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1304 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1305 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1306 ProtocolStr
= 0, Comment
= 0;
1307 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1308 UINT i
,SizeNeeded
= 0,
1309 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1310 DWORD ReadSize
= 0, ValidData
= 0;
1311 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1315 WSASetLastError( WSANOTINITIALISED
);
1321 WSASetLastError( WSANO_RECOVERY
);
1325 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1327 WSASetLastError( WSANO_RECOVERY
);
1328 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1329 return NULL
; /* Can't get system directory */
1332 strncat(SystemDirectory
,
1333 ServicesFileLocation
,
1336 ServicesFile
= CreateFileA(SystemDirectory
,
1341 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1344 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1346 WSASetLastError( WSANO_RECOVERY
);
1350 /* Scan the services file ...
1352 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1353 * contain a full line, then we will try to read more.
1355 * We fall from the loop if the buffer does not have a line terminator.
1360 ReadFile(ServicesFile
,
1361 ServiceDBData
+ ValidData
,
1362 sizeof( ServiceDBData
) - ValidData
,
1365 ValidData
+= ReadSize
;
1367 NextLine
= ThisLine
= ServiceDBData
;
1369 /* Find the beginning of the next line */
1370 while( NextLine
< ServiceDBData
+ ValidData
&&
1371 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1373 /* Zero and skip, so we can treat what we have as a string */
1374 if( NextLine
> ServiceDBData
+ ValidData
)
1377 *NextLine
= 0; NextLine
++;
1379 Comment
= strchr( ThisLine
, '#' );
1380 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1382 if(DecodeServEntFromString(ThisLine
,
1387 WS2_INTERNAL_MAX_ALIAS
) &&
1388 (htons(atoi( PortNumberStr
)) == port
) &&
1389 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1392 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1395 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1396 (NextLine
- ThisLine
);
1400 /* Get rid of everything we read so far */
1401 while( NextLine
<= ServiceDBData
+ ValidData
&&
1402 isspace( *NextLine
) )
1407 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1408 ServiceDBData
+ ValidData
- NextLine
));
1410 memmove(ServiceDBData
,
1412 ServiceDBData
+ ValidData
- NextLine
);
1413 ValidData
-= NextLine
- ServiceDBData
;
1414 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1417 /* This we'll do no matter what */
1418 CloseHandle( ServicesFile
);
1422 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1423 WSASetLastError( WSANO_DATA
);
1427 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1429 /* Free previous getservbyport buffer, allocate bigger */
1430 if( p
->Getservbyport
)
1431 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1432 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1435 if( !p
->Getservbyport
)
1437 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1439 WSASetLastError( WSATRY_AGAIN
);
1442 p
->Getservbyport
->Size
= SizeNeeded
;
1445 memmove(p
->Getservbyport
->Data
,
1447 NextLine
- ThisLine
);
1449 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1450 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1451 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1452 PortNumberStr
, ProtocolStr
));
1454 for( i
= 0; Aliases
[i
]; i
++ )
1456 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1457 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1460 memcpy(p
->Getservbyport
->Aliases
,Aliases
,sizeof(Aliases
));
1462 /* Create the struct proper */
1463 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1464 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1465 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1466 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1468 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1470 return &p
->Getservbyport
->ServerEntry
;
1480 inet_addr(IN CONST CHAR FAR
* cp
)
1482 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1484 * cp = Pointer to string with address to convert
1486 * Binary representation of IPv4 address, or INADDR_NONE
1497 WSASetLastError(WSAEFAULT
);
1504 if (strcmp(p
, " ") == 0)
1507 for (i
= 0; i
<= 3; i
++)
1509 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1529 inet_ntoa(IN IN_ADDR in
)
1534 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1535 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1537 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1540 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1543 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1547 return (CHAR FAR
*)p
;
1556 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1558 struct addrinfo
*next
, *cur
;
1562 next
= cur
->ai_next
;
1564 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1565 if (cur
->ai_canonname
)
1566 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1567 HeapFree(GetProcessHeap(), 0, cur
);
1574 new_addrinfo(struct addrinfo
*prev
)
1576 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1578 prev
->ai_next
= ret
;
1587 getaddrinfo(const char FAR
* nodename
,
1588 const char FAR
* servname
,
1589 const struct addrinfo FAR
* hints
,
1590 struct addrinfo FAR
* FAR
* res
)
1592 struct addrinfo
*ret
= NULL
, *ai
;
1598 DNS_STATUS dns_status
;
1599 PDNS_RECORD dp
, currdns
;
1600 struct sockaddr_in
*sin
;
1608 if (nodename
== NULL
&& servname
== NULL
)
1610 error
= WSAHOST_NOT_FOUND
;
1614 if (!WSAINITIALIZED
)
1616 error
= WSANOTINITIALISED
;
1622 /* converting port number */
1623 port
= strtoul(servname
, NULL
, 10);
1624 /* service name was specified? */
1627 /* protocol was specified? */
1628 if (hints
&& hints
->ai_protocol
)
1630 pent
= getprotobynumber(hints
->ai_protocol
);
1636 proto
= pent
->p_name
;
1640 se
= getservbyname(servname
, proto
);
1643 error
= WSATYPE_NOT_FOUND
;
1656 /* Is it an IPv6 address? */
1657 if (strstr(nodename
, ":"))
1659 error
= WSAHOST_NOT_FOUND
;
1663 /* Is it an IPv4 address? */
1664 addr
= inet_addr(nodename
);
1665 if (addr
!= INADDR_NONE
)
1667 ai
= new_addrinfo(NULL
);
1668 ai
->ai_family
= PF_INET
;
1669 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1670 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1671 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1672 sin
->sin_family
= AF_INET
;
1673 sin
->sin_port
= port
;
1674 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1677 if (ai
->ai_socktype
== 0)
1678 ai
->ai_socktype
= hints
->ai_socktype
;
1679 if (ai
->ai_protocol
== 0)
1680 ai
->ai_protocol
= hints
->ai_protocol
;
1686 /* resolving host name */
1687 dns_status
= DnsQuery_A(nodename
,
1691 /* extra dns servers */ &dp
,
1694 if (dns_status
== 0)
1697 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1699 /* accept only A records */
1700 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1702 ai
= new_addrinfo(ai
);
1705 ai
->ai_family
= PF_INET
;
1706 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1707 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1708 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1709 sin
->sin_family
= AF_INET
;
1710 sin
->sin_port
= port
;
1711 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1714 if (ai
->ai_socktype
== 0)
1715 ai
->ai_socktype
= hints
->ai_socktype
;
1716 if (ai
->ai_protocol
== 0)
1717 ai
->ai_protocol
= hints
->ai_protocol
;
1720 DnsRecordListFree(dp
, DnsFreeRecordList
);
1726 ai
= new_addrinfo(NULL
);
1727 ai
->ai_family
= PF_INET
;
1728 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1729 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1730 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1731 sin
->sin_family
= AF_INET
;
1732 sin
->sin_port
= port
;
1735 if (!(hints
->ai_flags
& AI_PASSIVE
))
1737 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1738 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1739 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1740 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1742 if (ai
->ai_socktype
== 0)
1743 ai
->ai_socktype
= hints
->ai_socktype
;
1744 if (ai
->ai_protocol
== 0)
1745 ai
->ai_protocol
= hints
->ai_protocol
;
1752 error
= WSAHOST_NOT_FOUND
;
1756 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1759 error
= WSAEAFNOSUPPORT
;
1767 WSASetLastError(error
);