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
21 #ifndef MAX_HOSTNAME_LEN
22 #define MAX_HOSTNAME_LEN 256
25 /* Name resolution APIs */
32 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress
,
33 IN DWORD dwAddressLength
,
34 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
35 OUT LPSTR lpszAddressString
,
36 IN OUT LPDWORD lpdwAddressStringLength
)
39 CHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
42 if (!lpsaAddress
) return SOCKET_ERROR
;
43 if (!lpszAddressString
|| !lpdwAddressStringLength
) return SOCKET_ERROR
;
45 switch(lpsaAddress
->sa_family
)
48 if (dwAddressLength
< sizeof(SOCKADDR_IN
)) return SOCKET_ERROR
;
49 sprintf( buffer
, "%u.%u.%u.%u:%u",
50 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 24 & 0xff),
51 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 16 & 0xff),
52 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 8 & 0xff),
53 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) & 0xff),
54 ntohs( ((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) );
56 p
= strchr( buffer
, ':' );
57 if (!((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) *p
= 0;
60 WSASetLastError(WSAEINVAL
);
64 size
= strlen( buffer
) + 1;
66 if (*lpdwAddressStringLength
< size
)
68 *lpdwAddressStringLength
= size
;
69 WSASetLastError(WSAEFAULT
);
73 *lpdwAddressStringLength
= size
;
74 strcpy( lpszAddressString
, buffer
);
84 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
85 IN DWORD dwAddressLength
,
86 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
87 OUT LPWSTR lpszAddressString
,
88 IN OUT LPDWORD lpdwAddressStringLength
)
92 WCHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
95 size
= *lpdwAddressStringLength
;
96 ret
= WSAAddressToStringA(lpsaAddress
, dwAddressLength
, NULL
, bufAddr
, &size
);
100 MultiByteToWideChar( CP_ACP
, 0, bufAddr
, size
, buffer
, sizeof( buffer
)/sizeof(WCHAR
));
102 if (*lpdwAddressStringLength
< size
)
104 *lpdwAddressStringLength
= size
;
105 WSASetLastError(WSAEFAULT
);
109 *lpdwAddressStringLength
= size
;
110 lstrcpyW( lpszAddressString
, buffer
);
120 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
121 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
125 WSASetLastError(WSASYSCALLFAILURE
);
135 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
136 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
140 WSASetLastError(WSASYSCALLFAILURE
);
150 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
151 IN LPGUID lpServiceClassId
,
152 IN OUT LPDWORD lpdwBufferLength
,
153 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
157 WSASetLastError(WSASYSCALLFAILURE
);
167 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
168 IN LPGUID lpServiceClassId
,
169 IN OUT LPDWORD lpdwBufferLength
,
170 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
174 WSASetLastError(WSASYSCALLFAILURE
);
184 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
185 OUT LPSTR lpszServiceClassName
,
186 IN OUT LPDWORD lpdwBufferLength
)
190 WSASetLastError(WSASYSCALLFAILURE
);
200 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
201 OUT LPWSTR lpszServiceClassName
,
202 IN OUT LPDWORD lpdwBufferLength
)
206 WSASetLastError(WSASYSCALLFAILURE
);
216 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
220 WSASetLastError(WSASYSCALLFAILURE
);
230 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
234 WSASetLastError(WSASYSCALLFAILURE
);
244 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
245 IN DWORD dwControlFlags
,
246 OUT LPHANDLE lphLookup
)
250 WSASetLastError(WSASYSCALLFAILURE
);
260 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
261 IN DWORD dwControlFlags
,
262 OUT LPHANDLE lphLookup
)
266 WSASetLastError(WSASYSCALLFAILURE
);
276 WSALookupServiceEnd(IN HANDLE hLookup
)
280 WSASetLastError(WSASYSCALLFAILURE
);
290 WSALookupServiceNextA(IN HANDLE hLookup
,
291 IN DWORD dwControlFlags
,
292 IN OUT LPDWORD lpdwBufferLength
,
293 OUT LPWSAQUERYSETA lpqsResults
)
297 WSASetLastError(WSASYSCALLFAILURE
);
307 WSALookupServiceNextW(IN HANDLE hLookup
,
308 IN DWORD dwControlFlags
,
309 IN OUT LPDWORD lpdwBufferLength
,
310 OUT LPWSAQUERYSETW lpqsResults
)
314 WSASetLastError(WSASYSCALLFAILURE
);
324 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
328 WSASetLastError(WSASYSCALLFAILURE
);
338 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
339 IN WSAESETSERVICEOP essOperation
,
340 IN DWORD dwControlFlags
)
344 WSASetLastError(WSASYSCALLFAILURE
);
354 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
355 IN WSAESETSERVICEOP essOperation
,
356 IN DWORD dwControlFlags
)
360 WSASetLastError(WSASYSCALLFAILURE
);
370 WSAStringToAddressA(IN LPSTR AddressString
,
371 IN INT AddressFamily
,
372 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
373 OUT LPSOCKADDR lpAddress
,
374 IN OUT LPINT lpAddressLength
)
378 WSAPROTOCOL_INFOW ProtoInfoW
;
380 len
= MultiByteToWideChar(CP_ACP
,
387 szTemp
= HeapAlloc(GetProcessHeap(),
389 len
* sizeof(WCHAR
));
391 MultiByteToWideChar(CP_ACP
,
402 FIELD_OFFSET(WSAPROTOCOL_INFOA
, szProtocol
));
404 MultiByteToWideChar(CP_ACP
,
406 lpProtocolInfo
->szProtocol
,
408 ProtoInfoW
.szProtocol
,
409 WSAPROTOCOL_LEN
+ 1);
412 ret
= WSAStringToAddressW(szTemp
,
418 HeapFree(GetProcessHeap(),
422 WSASetLastError(ret
);
433 WSAStringToAddressW(IN LPWSTR AddressString
,
434 IN INT AddressFamily
,
435 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
436 OUT LPSOCKADDR lpAddress
,
437 IN OUT LPINT lpAddressLength
)
443 SOCKADDR_IN
*sockaddr
;
445 if (!lpAddressLength
|| !lpAddress
|| !AddressString
)
447 WSASetLastError(WSAEINVAL
);
451 sockaddr
= (SOCKADDR_IN
*) lpAddress
;
453 /* Set right adress family */
454 if (lpProtocolInfo
!=NULL
)
455 sockaddr
->sin_family
= lpProtocolInfo
->iAddressFamily
;
457 sockaddr
->sin_family
= AddressFamily
;
460 if (AddressFamily
== AF_INET
)
462 if (*lpAddressLength
< (INT
)sizeof(SOCKADDR_IN
))
464 *lpAddressLength
= sizeof(SOCKADDR_IN
);
469 // translate ip string to ip
471 /* rest sockaddr.sin_addr.s_addr
472 for we need to be sure it is zero when we come to while */
473 memset(lpAddress
,0,sizeof(SOCKADDR_IN
));
475 /* Set right adress family */
476 sockaddr
->sin_family
= AF_INET
;
478 /* Get port number */
479 pos
= wcscspn(AddressString
,L
":") + 1;
481 if (pos
< (int)wcslen(AddressString
))
482 sockaddr
->sin_port
= wcstol(&AddressString
[pos
],
487 sockaddr
->sin_port
= 0;
493 while (pos
< (int)wcslen(AddressString
))
495 inetaddr
= (inetaddr
<<8) + ((UCHAR
)wcstol(&AddressString
[pos
],
498 pos
+= wcscspn( &AddressString
[pos
],L
".") +1 ;
502 sockaddr
->sin_addr
.s_addr
= inetaddr
;
507 WSASetLastError(res
);
512 void check_hostent(struct hostent
**he
)
514 struct hostent
*new_he
;
516 WS_DbgPrint(MID_TRACE
,("*he: %x\n",*he
));
520 new_he
= HeapAlloc(GlobalHeap
,
522 sizeof(struct hostent
) + MAX_HOSTNAME_LEN
+ 1);
524 new_he
->h_name
= (PCHAR
)(new_he
+ 1);
525 new_he
->h_aliases
= NULL
;
526 new_he
->h_addrtype
= 0; // AF_INET
527 new_he
->h_length
= 0; // sizeof(in_addr)
528 new_he
->h_addr_list
= HeapAlloc(GlobalHeap
,
536 void populate_hostent(struct hostent
*he
, char* name
, IP4_ADDRESS addr
)
540 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
541 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
547 if( !he
->h_aliases
) {
548 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
549 he
->h_aliases
[0] = NULL
;
551 he
->h_addrtype
= AF_INET
;
552 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
554 if( he
->h_addr_list
[0] )
561 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
563 MAX_HOSTNAME_LEN
+ 1);
565 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
567 RtlCopyMemory(he
->h_addr_list
[0],
571 he
->h_addr_list
[1] = NULL
;
574 void free_hostent(struct hostent
*he
)
581 HeapFree(GlobalHeap
, 0, he
->h_name
);
584 for (i
= 0; he
->h_aliases
[i
]; i
++)
585 HeapFree(GlobalHeap
, 0, he
->h_aliases
[i
]);
586 HeapFree(GlobalHeap
, 0, he
->h_aliases
);
590 for (i
= 0; he
->h_addr_list
[i
]; i
++)
591 HeapFree(GlobalHeap
, 0, he
->h_addr_list
[i
]);
592 HeapFree(GlobalHeap
, 0, he
->h_addr_list
);
594 HeapFree(GlobalHeap
, 0, he
);
598 /* WinSock 1.1 compatible name resolution APIs */
605 gethostbyaddr(IN CONST CHAR FAR
* addr
,
611 return (LPHOSTENT
)NULL
;
615 Assumes rfc 1123 - adam *
617 addr[0] = inet_addr(name);
618 strcpy( hostname, name );
619 if(addr[0] == 0xffffffff) return NULL;
620 he.h_addr_list = (void *)addr;
621 he.h_name = hostname;
623 he.h_addrtype = AF_INET;
624 he.h_length = sizeof(addr);
628 From the MSDN Platform SDK: Windows Sockets 2
629 "The gethostbyname function cannot resolve IP address strings passed to it.
630 Such a request is treated exactly as if an unknown host name were passed."
633 Defferring to the the documented behaviour, rather than the unix behaviour
634 What if the hostname is in the HOSTS file? see getservbyname
639 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
640 /* see ws2_32.h, winsock2.h*/
641 /*getnetworkparameters - iphlp api */
645 servent -- w32api/include/winsock2.h
646 PWINSOCK_THREAD_BLOCK -- ws2_32.h
647 dllmain.c -- threadlocal memory allocation / deallocation
652 /* lib/adns/src/adns.h XXX */
662 #define h_addr h_addr_list[0]
672 struct hostent defined in w32api/include/winsock2.h
675 void free_servent(struct servent
* s
)
682 HeapFree(GlobalHeap
, 0, s
->s_name
);
685 for (i
= 0; s
->s_aliases
[i
]; i
++)
686 HeapFree(GlobalHeap
, 0, s
->s_aliases
[i
]);
687 HeapFree(GlobalHeap
, 0, s
->s_aliases
);
690 HeapFree(GlobalHeap
, 0, s
->s_proto
);
691 HeapFree(GlobalHeap
, 0, s
);
695 /* This function is far from perfect but it works enough */
698 FindEntryInHosts(IN CONST CHAR FAR
* name
)
702 CHAR HostsDBData
[BUFSIZ
] = { 0 };
703 PCHAR SystemDirectory
= HostsDBData
;
704 PCHAR HostsLocation
= "\\drivers\\etc\\hosts";
705 PCHAR AddressStr
, DnsName
= NULL
, AddrTerm
, NameSt
, NextLine
, ThisLine
, Comment
;
706 UINT SystemDirSize
= sizeof(HostsDBData
) - 1, ValidData
= 0;
709 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
711 /* We assume that the parameters are valid */
713 if (!GetSystemDirectoryA(SystemDirectory
, SystemDirSize
))
715 WSASetLastError(WSANO_RECOVERY
);
716 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
717 return NULL
; /* Can't get system directory */
720 strncat(SystemDirectory
,
724 HostsFile
= CreateFileA(SystemDirectory
,
729 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
731 if (HostsFile
== INVALID_HANDLE_VALUE
)
733 WSASetLastError(WSANO_RECOVERY
);
739 HostsDBData
+ ValidData
,
740 sizeof(HostsDBData
) - ValidData
,
744 ValidData
+= ReadSize
;
746 NextLine
= ThisLine
= HostsDBData
;
748 /* Find the beginning of the next line */
749 while(NextLine
< HostsDBData
+ ValidData
&&
750 *NextLine
!= '\r' && *NextLine
!= '\n' )
755 /* Zero and skip, so we can treat what we have as a string */
756 if( NextLine
> HostsDBData
+ ValidData
)
759 *NextLine
= 0; NextLine
++;
761 Comment
= strchr( ThisLine
, '#' );
762 if( Comment
) *Comment
= 0; /* Terminate at comment start */
764 AddressStr
= ThisLine
;
765 /* Find the first space separating the IP address from the DNS name */
766 AddrTerm
= strchr(ThisLine
, ' ');
769 /* Terminate the address string */
772 /* Find the last space before the DNS name */
773 NameSt
= strrchr(ThisLine
, ' ');
775 /* If there is only one space (the one we removed above), then just use the address terminator */
779 /* Move from the space to the first character of the DNS name */
784 if (!strcmp(name
, DnsName
))
791 /* Get rid of everything we read so far */
792 while( NextLine
<= HostsDBData
+ ValidData
&&
798 if (HostsDBData
+ ValidData
- NextLine
<= 0)
801 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
802 HostsDBData
+ ValidData
- NextLine
));
806 HostsDBData
+ ValidData
- NextLine
);
807 ValidData
-= NextLine
- HostsDBData
;
808 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
811 CloseHandle(HostsFile
);
815 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
816 WSASetLastError(WSANO_DATA
);
820 if (strstr(AddressStr
, ":"))
822 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
823 WSASetLastError(WSAEINVAL
);
827 Address
= inet_addr(AddressStr
);
828 if (Address
== INADDR_NONE
)
830 WSASetLastError(WSAEINVAL
);
834 populate_hostent(p
->Hostent
, DnsName
, Address
);
841 gethostbyname(IN CONST CHAR FAR
* name
)
850 typedef enum addr_type addr_type
;
854 DNS_STATUS dns_status
= {0};
855 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
857 PWINSOCK_THREAD_BLOCK p
;
862 p
= NtCurrentTeb()->WinSockData
;
864 if (!p
|| !WSAINITIALIZED
)
866 WSASetLastError( WSANOTINITIALISED
);
870 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
872 /* Hostname NULL - behave like gethostname */
875 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
878 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
884 /* Is it an IPv6 address? */
885 found
= strstr(name
, ":");
892 /* Is it an IPv4 address? */
893 if (!isalpha(name
[0]))
899 addr
= GH_RFC1123_DNS
;
901 /* Broken out in case we want to get fancy later */
906 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
911 WSASetLastError(WSAEFAULT
);
915 /* Note: If passed an IP address, MSDN says that gethostbyname()
916 treats it as an unknown host.
917 This is different from the unix implementation. Use inet_addr()
921 /* DNS_TYPE_A: include/WinDNS.h */
922 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
924 /* Look for the DNS name in the hosts file */
925 Hostent
= FindEntryInHosts(name
);
929 dns_status
= DnsQuery_A(name
,
933 /* extra dns servers */ &dp
,
938 //ASSERT(dp->wType == DNS_TYPE_A);
939 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
942 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
945 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
951 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
952 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
953 populate_hostent(p
->Hostent
,
955 curr
->Data
.A
.IpAddress
);
956 DnsRecordListFree(dp
, DnsFreeRecordList
);
961 DnsRecordListFree(dp
, DnsFreeRecordList
);
965 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
967 WSASetLastError(WSAHOST_NOT_FOUND
);
973 WSASetLastError(WSANO_RECOVERY
);
978 WSASetLastError(WSANO_RECOVERY
);
987 gethostname(OUT CHAR FAR
* name
,
990 DWORD size
= namelen
;
992 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
997 WSASetLastError(WSAEFAULT
);
1002 name
[namelen
-1] = '\0';
1009 * XXX arty -- Partial implementation pending a better one. This one will
1010 * do for normal purposes.#include <ws2_32.h>
1012 * Return the address of a static LPPROTOENT corresponding to the named
1013 * protocol. These structs aren't very interesting, so I'm not too ashamed
1014 * to have this function work on builtins for now.
1019 static CHAR
*no_aliases
= 0;
1020 static PROTOENT protocols
[] =
1022 {"icmp",&no_aliases
, IPPROTO_ICMP
},
1023 {"tcp", &no_aliases
, IPPROTO_TCP
},
1024 {"udp", &no_aliases
, IPPROTO_UDP
},
1030 getprotobyname(IN CONST CHAR FAR
* name
)
1033 for (i
= 0; protocols
[i
].p_name
; i
++)
1035 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
1036 return &protocols
[i
];
1046 getprotobynumber(IN INT number
)
1049 for (i
= 0; protocols
[i
].p_name
; i
++)
1051 if (protocols
[i
].p_proto
== number
)
1052 return &protocols
[i
];
1057 #define SKIPWS(ptr,act) \
1058 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1059 #define SKIPANDMARKSTR(ptr,act) \
1060 {while(*ptr && !isspace(*ptr)) ptr++; \
1061 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1065 DecodeServEntFromString(IN PCHAR ServiceString
,
1066 OUT PCHAR
*ServiceName
,
1067 OUT PCHAR
*PortNumberStr
,
1068 OUT PCHAR
*ProtocolStr
,
1074 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
1076 SKIPWS(ServiceString
, return FALSE
);
1077 *ServiceName
= ServiceString
;
1078 SKIPANDMARKSTR(ServiceString
, return FALSE
);
1079 SKIPWS(ServiceString
, return FALSE
);
1080 *PortNumberStr
= ServiceString
;
1081 SKIPANDMARKSTR(ServiceString
, ;);
1083 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
1085 SKIPWS(ServiceString
, break);
1086 if( *ServiceString
)
1088 SKIPANDMARKSTR(ServiceString
, ;);
1089 if( strlen(ServiceString
) )
1091 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
1092 *Aliases
++ = ServiceString
;
1099 *ProtocolStr
= strchr(*PortNumberStr
,'/');
1100 if( !*ProtocolStr
) return FALSE
;
1101 **ProtocolStr
= 0; (*ProtocolStr
)++;
1103 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
1104 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
1110 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1117 getservbyname(IN CONST CHAR FAR
* name
,
1118 IN CONST CHAR FAR
* proto
)
1121 HANDLE ServicesFile
;
1122 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1123 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1124 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1125 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1126 ProtocolStr
= 0, Comment
= 0, EndValid
;
1127 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1128 UINT i
,SizeNeeded
= 0,
1129 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1131 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1133 if (!p
|| !WSAINITIALIZED
)
1135 WSASetLastError( WSANOTINITIALISED
);
1141 WSASetLastError( WSANO_RECOVERY
);
1145 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1147 WSASetLastError( WSANO_RECOVERY
);
1148 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1149 return NULL
; /* Can't get system directory */
1152 strncat(SystemDirectory
,
1153 ServicesFileLocation
,
1156 ServicesFile
= CreateFileA(SystemDirectory
,
1161 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1164 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1166 WSASetLastError( WSANO_RECOVERY
);
1170 /* Scan the services file ...
1172 * We will be share the buffer on the lines. If the line does not fit in
1173 * the buffer, then moving it to the beginning of the buffer and read
1174 * the remnants of line from file.
1178 ReadFile(ServicesFile
,
1180 sizeof( ServiceDBData
) - 1,
1182 ThisLine
= NextLine
= ServiceDBData
;
1183 EndValid
= ServiceDBData
+ ReadSize
;
1184 ServiceDBData
[sizeof(ServiceDBData
) - 1] = '\0';
1188 for(; *NextLine
!= '\r' && *NextLine
!= '\n'; NextLine
++)
1190 if(NextLine
== EndValid
)
1192 int LineLen
= NextLine
- ThisLine
;
1194 if(ThisLine
== ServiceDBData
)
1196 WS_DbgPrint(MIN_TRACE
,("Line too long"));
1197 WSASetLastError( WSANO_RECOVERY
);
1201 memmove(ServiceDBData
, ThisLine
, LineLen
);
1203 ReadFile(ServicesFile
, ServiceDBData
+ LineLen
,
1204 sizeof( ServiceDBData
)-1 - LineLen
,
1207 EndValid
= ServiceDBData
+ LineLen
+ ReadSize
;
1208 NextLine
= ServiceDBData
+ LineLen
;
1209 ThisLine
= ServiceDBData
;
1211 if(!ReadSize
) break;
1216 Comment
= strchr( ThisLine
, '#' );
1217 if( Comment
) *Comment
= '\0'; /* Terminate at comment start */
1219 if(DecodeServEntFromString(ThisLine
,
1224 WS2_INTERNAL_MAX_ALIAS
) &&
1225 !strcmp( ServiceName
, name
) &&
1226 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1229 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1231 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1232 (NextLine
- ThisLine
);
1236 ThisLine
= NextLine
;
1239 /* This we'll do no matter what */
1240 CloseHandle( ServicesFile
);
1244 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1245 WSASetLastError( WSANO_DATA
);
1249 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1251 /* Free previous getservbyname buffer, allocate bigger */
1252 if( p
->Getservbyname
)
1253 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1254 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1255 if( !p
->Getservbyname
)
1257 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1259 WSASetLastError( WSATRY_AGAIN
);
1262 p
->Getservbyname
->Size
= SizeNeeded
;
1266 memmove(p
->Getservbyname
->Data
,
1268 NextLine
- ThisLine
);
1270 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1271 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1272 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1276 for( i
= 0; Aliases
[i
]; i
++ )
1278 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1279 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1282 memcpy(p
->Getservbyname
->Aliases
,
1286 /* Create the struct proper */
1287 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1288 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1289 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1290 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1292 return &p
->Getservbyname
->ServerEntry
;
1301 getservbyport(IN INT port
,
1302 IN CONST CHAR FAR
* proto
)
1305 HANDLE ServicesFile
;
1306 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1307 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1308 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1309 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1310 ProtocolStr
= 0, Comment
= 0;
1311 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1312 UINT i
,SizeNeeded
= 0,
1313 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1314 DWORD ReadSize
= 0, ValidData
= 0;
1315 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1317 if( !p
|| !WSAINITIALIZED
)
1319 WSASetLastError( WSANOTINITIALISED
);
1325 WSASetLastError( WSANO_RECOVERY
);
1329 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1331 WSASetLastError( WSANO_RECOVERY
);
1332 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1333 return NULL
; /* Can't get system directory */
1336 strncat(SystemDirectory
,
1337 ServicesFileLocation
,
1340 ServicesFile
= CreateFileA(SystemDirectory
,
1345 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1348 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1350 WSASetLastError( WSANO_RECOVERY
);
1354 /* Scan the services file ...
1356 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1357 * contain a full line, then we will try to read more.
1359 * We fall from the loop if the buffer does not have a line terminator.
1364 ReadFile(ServicesFile
,
1365 ServiceDBData
+ ValidData
,
1366 sizeof( ServiceDBData
) - ValidData
,
1369 ValidData
+= ReadSize
;
1371 NextLine
= ThisLine
= ServiceDBData
;
1373 /* Find the beginning of the next line */
1374 while( NextLine
< ServiceDBData
+ ValidData
&&
1375 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1377 /* Zero and skip, so we can treat what we have as a string */
1378 if( NextLine
> ServiceDBData
+ ValidData
)
1381 *NextLine
= 0; NextLine
++;
1383 Comment
= strchr( ThisLine
, '#' );
1384 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1386 if(DecodeServEntFromString(ThisLine
,
1391 WS2_INTERNAL_MAX_ALIAS
) &&
1392 (htons(atoi( PortNumberStr
)) == port
) &&
1393 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1396 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1399 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1400 (NextLine
- ThisLine
);
1404 /* Get rid of everything we read so far */
1405 while( NextLine
<= ServiceDBData
+ ValidData
&&
1406 isspace( *NextLine
) )
1411 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1412 ServiceDBData
+ ValidData
- NextLine
));
1414 memmove(ServiceDBData
,
1416 ServiceDBData
+ ValidData
- NextLine
);
1417 ValidData
-= NextLine
- ServiceDBData
;
1418 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1421 /* This we'll do no matter what */
1422 CloseHandle( ServicesFile
);
1426 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1427 WSASetLastError( WSANO_DATA
);
1431 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1433 /* Free previous getservbyport buffer, allocate bigger */
1434 if( p
->Getservbyport
)
1435 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1436 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1439 if( !p
->Getservbyport
)
1441 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1443 WSASetLastError( WSATRY_AGAIN
);
1446 p
->Getservbyport
->Size
= SizeNeeded
;
1449 memmove(p
->Getservbyport
->Data
,
1451 NextLine
- ThisLine
);
1453 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1454 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1455 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1456 PortNumberStr
, ProtocolStr
));
1458 for( i
= 0; Aliases
[i
]; i
++ )
1460 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1461 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1464 memcpy(p
->Getservbyport
->Aliases
,Aliases
,sizeof(Aliases
));
1466 /* Create the struct proper */
1467 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1468 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1469 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1470 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1472 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1474 return &p
->Getservbyport
->ServerEntry
;
1484 inet_addr(IN CONST CHAR FAR
* cp
)
1486 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1488 * cp = Pointer to string with address to convert
1490 * Binary representation of IPv4 address, or INADDR_NONE
1499 if (!p
|| !WSAINITIALIZED
)
1501 WSASetLastError(WSAEFAULT
);
1508 if (strcmp(p
, " ") == 0)
1511 for (i
= 0; i
<= 3; i
++)
1513 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1533 inet_ntoa(IN IN_ADDR in
)
1538 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1539 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1541 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1544 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1547 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1551 return (CHAR FAR
*)p
;
1560 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1562 struct addrinfo
*next
, *cur
;
1566 next
= cur
->ai_next
;
1568 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1569 if (cur
->ai_canonname
)
1570 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1571 HeapFree(GetProcessHeap(), 0, cur
);
1578 new_addrinfo(struct addrinfo
*prev
)
1580 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1582 prev
->ai_next
= ret
;
1591 getaddrinfo(const char FAR
* nodename
,
1592 const char FAR
* servname
,
1593 const struct addrinfo FAR
* hints
,
1594 struct addrinfo FAR
* FAR
* res
)
1596 struct addrinfo
*ret
= NULL
, *ai
;
1603 DNS_STATUS dns_status
;
1604 PDNS_RECORD dp
, currdns
;
1605 struct sockaddr_in
*sin
;
1613 if (nodename
== NULL
&& servname
== NULL
)
1615 error
= WSAHOST_NOT_FOUND
;
1619 if (!WSAINITIALIZED
)
1621 error
= WSANOTINITIALISED
;
1627 /* converting port number */
1628 port
= strtoul(servname
, &pc
, 10);
1629 /* service name was specified? */
1630 if (*pc
!= ANSI_NULL
)
1632 /* protocol was specified? */
1633 if (hints
&& hints
->ai_protocol
)
1635 pent
= getprotobynumber(hints
->ai_protocol
);
1641 proto
= pent
->p_name
;
1645 se
= getservbyname(servname
, proto
);
1648 error
= WSATYPE_NOT_FOUND
;
1661 /* Is it an IPv6 address? */
1662 if (strstr(nodename
, ":"))
1664 error
= WSAHOST_NOT_FOUND
;
1668 /* Is it an IPv4 address? */
1669 addr
= inet_addr(nodename
);
1670 if (addr
!= INADDR_NONE
)
1672 ai
= new_addrinfo(NULL
);
1673 ai
->ai_family
= PF_INET
;
1674 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1675 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1676 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1677 sin
->sin_family
= AF_INET
;
1678 sin
->sin_port
= port
;
1679 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1682 if (ai
->ai_socktype
== 0)
1683 ai
->ai_socktype
= hints
->ai_socktype
;
1684 if (ai
->ai_protocol
== 0)
1685 ai
->ai_protocol
= hints
->ai_protocol
;
1691 /* resolving host name */
1692 dns_status
= DnsQuery_A(nodename
,
1696 /* extra dns servers */ &dp
,
1699 if (dns_status
== 0)
1702 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1704 /* accept only A records */
1705 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1707 ai
= new_addrinfo(ai
);
1710 ai
->ai_family
= PF_INET
;
1711 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1712 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1713 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1714 sin
->sin_family
= AF_INET
;
1715 sin
->sin_port
= port
;
1716 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1719 if (ai
->ai_socktype
== 0)
1720 ai
->ai_socktype
= hints
->ai_socktype
;
1721 if (ai
->ai_protocol
== 0)
1722 ai
->ai_protocol
= hints
->ai_protocol
;
1725 DnsRecordListFree(dp
, DnsFreeRecordList
);
1731 ai
= new_addrinfo(NULL
);
1732 ai
->ai_family
= PF_INET
;
1733 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1734 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1735 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1736 sin
->sin_family
= AF_INET
;
1737 sin
->sin_port
= port
;
1740 if (!(hints
->ai_flags
& AI_PASSIVE
))
1742 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1743 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1744 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1745 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1747 if (ai
->ai_socktype
== 0)
1748 ai
->ai_socktype
= hints
->ai_socktype
;
1749 if (ai
->ai_protocol
== 0)
1750 ai
->ai_protocol
= hints
->ai_protocol
;
1757 error
= WSAHOST_NOT_FOUND
;
1761 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1764 error
= WSAEAFNOSUPPORT
;
1772 WSASetLastError(error
);