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
= 0;
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
,
528 RtlZeroMemory(new_he
->h_addr_list
,
534 void populate_hostent(struct hostent
*he
, char* name
, DNS_A_DATA addr
)
538 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
539 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
545 if( !he
->h_aliases
) {
546 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
547 he
->h_aliases
[0] = 0;
549 he
->h_addrtype
= AF_INET
;
550 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
552 if( he
->h_addr_list
[0] )
559 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
561 MAX_HOSTNAME_LEN
+ 1);
563 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
565 RtlCopyMemory(he
->h_addr_list
[0],
566 (char*)&addr
.IpAddress
,
567 sizeof(addr
.IpAddress
));
569 he
->h_addr_list
[1] = 0;
573 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
574 void free_hostent(struct hostent
*he
)
582 next
= he
->h_aliases
[0];
583 while(next
) { HFREE(next
); next
++; }
587 next
= he
->h_addr_list
[0];
588 while(next
) { HFREE(next
); next
++; }
590 HFREE(he
->h_addr_list
);
591 HFREE(he
->h_aliases
);
596 /* WinSock 1.1 compatible name resolution APIs */
603 gethostbyaddr(IN CONST CHAR FAR
* addr
,
609 return (LPHOSTENT
)NULL
;
613 Assumes rfc 1123 - adam *
615 addr[0] = inet_addr(name);
616 strcpy( hostname, name );
617 if(addr[0] == 0xffffffff) return NULL;
618 he.h_addr_list = (void *)addr;
619 he.h_name = hostname;
621 he.h_addrtype = AF_INET;
622 he.h_length = sizeof(addr);
626 From the MSDN Platform SDK: Windows Sockets 2
627 "The gethostbyname function cannot resolve IP address strings passed to it.
628 Such a request is treated exactly as if an unknown host name were passed."
631 Defferring to the the documented behaviour, rather than the unix behaviour
632 What if the hostname is in the HOSTS file? see getservbyname
637 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
638 /* see ws2_32.h, winsock2.h*/
639 /*getnetworkparameters - iphlp api */
643 servent -- w32api/include/winsock2.h
644 PWINSOCK_THREAD_BLOCK -- ws2_32.h
645 dllmain.c -- threadlocal memory allocation / deallocation
650 /* lib/adns/src/adns.h XXX */
660 #define h_addr h_addr_list[0]
670 struct hostent defined in w32api/include/winsock2.h
673 void free_servent(struct servent
* s
)
677 next
= s
->s_aliases
[0];
678 while(next
) { HFREE(next
); next
++; }
684 /* This function is far from perfect but it works enough */
687 FindEntryInHosts(IN CONST CHAR FAR
* name
)
691 CHAR HostsDBData
[BUFSIZ
] = { 0 };
692 PCHAR SystemDirectory
= HostsDBData
;
693 PCHAR HostsLocation
= "\\drivers\\etc\\hosts";
694 PCHAR AddressStr
, DnsName
= NULL
, AddrTerm
, NameSt
, NextLine
, ThisLine
, Comment
;
695 UINT SystemDirSize
= sizeof(HostsDBData
) - 1, ValidData
= 0;
698 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
700 /* We assume that the parameters are valid */
702 if (!GetSystemDirectoryA(SystemDirectory
, SystemDirSize
))
704 WSASetLastError(WSANO_RECOVERY
);
705 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
706 return NULL
; /* Can't get system directory */
709 strncat(SystemDirectory
,
713 HostsFile
= CreateFileA(SystemDirectory
,
718 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
720 if (HostsFile
== INVALID_HANDLE_VALUE
)
722 WSASetLastError(WSANO_RECOVERY
);
728 HostsDBData
+ ValidData
,
729 sizeof(HostsDBData
) - ValidData
,
733 ValidData
+= ReadSize
;
735 NextLine
= ThisLine
= HostsDBData
;
737 /* Find the beginning of the next line */
738 while(NextLine
< HostsDBData
+ ValidData
&&
739 *NextLine
!= '\r' && *NextLine
!= '\n' )
744 /* Zero and skip, so we can treat what we have as a string */
745 if( NextLine
> HostsDBData
+ ValidData
)
748 *NextLine
= 0; NextLine
++;
750 Comment
= strchr( ThisLine
, '#' );
751 if( Comment
) *Comment
= 0; /* Terminate at comment start */
753 AddressStr
= ThisLine
;
754 /* Find the first space separating the IP address from the DNS name */
755 AddrTerm
= strchr(ThisLine
, ' ');
758 /* Terminate the address string */
761 /* Find the last space before the DNS name */
762 NameSt
= strrchr(ThisLine
, ' ');
764 /* If there is only one space (the one we removed above), then just use the address terminator */
768 /* Move from the space to the first character of the DNS name */
773 if (!strcmp(name
, DnsName
))
780 /* Get rid of everything we read so far */
781 while( NextLine
<= HostsDBData
+ ValidData
&&
787 if (HostsDBData
+ ValidData
- NextLine
<= 0)
790 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
791 HostsDBData
+ ValidData
- NextLine
));
795 HostsDBData
+ ValidData
- NextLine
);
796 ValidData
-= NextLine
- HostsDBData
;
797 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
800 CloseHandle(HostsFile
);
804 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
805 WSASetLastError(WSANO_DATA
);
811 p
->Hostent
= HeapAlloc(GlobalHeap
, 0, sizeof(*p
->Hostent
));
814 WSASetLastError( WSATRY_AGAIN
);
819 p
->Hostent
->h_name
= HeapAlloc(GlobalHeap
, 0, strlen(DnsName
));
820 if( !p
->Hostent
->h_name
)
822 WSASetLastError( WSATRY_AGAIN
);
826 RtlCopyMemory(p
->Hostent
->h_name
,
830 p
->Hostent
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
831 if( !p
->Hostent
->h_aliases
)
833 WSASetLastError( WSATRY_AGAIN
);
837 p
->Hostent
->h_aliases
[0] = 0;
839 if (strstr(AddressStr
, ":"))
841 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
842 WSASetLastError(WSAEINVAL
);
846 p
->Hostent
->h_addrtype
= AF_INET
;
848 p
->Hostent
->h_addr_list
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
849 if( !p
->Hostent
->h_addr_list
)
851 WSASetLastError( WSATRY_AGAIN
);
855 Address
= inet_addr(AddressStr
);
856 if (Address
== INADDR_NONE
)
858 WSASetLastError(WSAEINVAL
);
862 p
->Hostent
->h_addr_list
[0] = HeapAlloc(GlobalHeap
, 0, sizeof(Address
));
863 if( !p
->Hostent
->h_addr_list
[0] )
865 WSASetLastError( WSATRY_AGAIN
);
869 RtlCopyMemory(p
->Hostent
->h_addr_list
[0],
873 p
->Hostent
->h_length
= sizeof(Address
);
880 gethostbyname(IN CONST CHAR FAR
* name
)
889 typedef enum addr_type addr_type
;
893 DNS_STATUS dns_status
= {0};
894 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
896 PWINSOCK_THREAD_BLOCK p
;
901 p
= NtCurrentTeb()->WinSockData
;
905 WSASetLastError( WSANOTINITIALISED
);
909 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
911 /* Hostname NULL - behave like gethostname */
914 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
917 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
923 /* Is it an IPv6 address? */
924 found
= strstr(name
, ":");
931 /* Is it an IPv4 address? */
932 if (!isalpha(name
[0]))
938 addr
= GH_RFC1123_DNS
;
940 /* Broken out in case we want to get fancy later */
945 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
950 WSASetLastError(WSAEFAULT
);
954 /* Note: If passed an IP address, MSDN says that gethostbyname()
955 treats it as an unknown host.
956 This is different from the unix implementation. Use inet_addr()
960 /* DNS_TYPE_A: include/WinDNS.h */
961 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
963 /* Look for the DNS name in the hosts file */
964 Hostent
= FindEntryInHosts(name
);
968 dns_status
= DnsQuery_A(name
,
972 /* extra dns servers */ &dp
,
977 //ASSERT(dp->wType == DNS_TYPE_A);
978 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
981 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
984 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
990 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
991 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
992 populate_hostent(p
->Hostent
, (PCHAR
)curr
->pName
, curr
->Data
.A
);
993 DnsRecordListFree(dp
, DnsFreeRecordList
);
998 DnsRecordListFree(dp
, DnsFreeRecordList
);
1002 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
1004 WSASetLastError(WSAHOST_NOT_FOUND
);
1010 WSASetLastError(WSANO_RECOVERY
);
1015 WSASetLastError(WSANO_RECOVERY
);
1024 gethostname(OUT CHAR FAR
* name
,
1027 DWORD size
= namelen
;
1029 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
1034 WSASetLastError(WSAEFAULT
);
1035 return SOCKET_ERROR
;
1039 name
[namelen
-1] = '\0';
1046 * XXX arty -- Partial implementation pending a better one. This one will
1047 * do for normal purposes.#include <ws2_32.h>
1049 * Return the address of a static LPPROTOENT corresponding to the named
1050 * protocol. These structs aren't very interesting, so I'm not too ashamed
1051 * to have this function work on builtins for now.
1056 static CHAR
*no_aliases
= 0;
1057 static PROTOENT protocols
[] =
1059 {"icmp",&no_aliases
, IPPROTO_ICMP
},
1060 {"tcp", &no_aliases
, IPPROTO_TCP
},
1061 {"udp", &no_aliases
, IPPROTO_UDP
},
1067 getprotobyname(IN CONST CHAR FAR
* name
)
1070 for (i
= 0; protocols
[i
].p_name
; i
++)
1072 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
1073 return &protocols
[i
];
1083 getprotobynumber(IN INT number
)
1086 for (i
= 0; protocols
[i
].p_name
; i
++)
1088 if (protocols
[i
].p_proto
== number
)
1089 return &protocols
[i
];
1094 #define SKIPWS(ptr,act) \
1095 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1096 #define SKIPANDMARKSTR(ptr,act) \
1097 {while(*ptr && !isspace(*ptr)) ptr++; \
1098 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1102 DecodeServEntFromString(IN PCHAR ServiceString
,
1103 OUT PCHAR
*ServiceName
,
1104 OUT PCHAR
*PortNumberStr
,
1105 OUT PCHAR
*ProtocolStr
,
1111 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
1113 SKIPWS(ServiceString
, return FALSE
);
1114 *ServiceName
= ServiceString
;
1115 SKIPANDMARKSTR(ServiceString
, return FALSE
);
1116 SKIPWS(ServiceString
, return FALSE
);
1117 *PortNumberStr
= ServiceString
;
1118 SKIPANDMARKSTR(ServiceString
, ;);
1120 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
1122 SKIPWS(ServiceString
, break);
1123 if( *ServiceString
)
1125 SKIPANDMARKSTR(ServiceString
, ;);
1126 if( strlen(ServiceString
) )
1128 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
1129 *Aliases
++ = ServiceString
;
1136 *ProtocolStr
= strchr(*PortNumberStr
,'/');
1137 if( !*ProtocolStr
) return FALSE
;
1138 **ProtocolStr
= 0; (*ProtocolStr
)++;
1140 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
1141 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
1147 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1154 getservbyname(IN CONST CHAR FAR
* name
,
1155 IN CONST CHAR FAR
* proto
)
1158 HANDLE ServicesFile
;
1159 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1160 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1161 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1162 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1163 ProtocolStr
= 0, Comment
= 0, EndValid
;
1164 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1165 UINT i
,SizeNeeded
= 0,
1166 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1168 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1172 WSASetLastError( WSANOTINITIALISED
);
1178 WSASetLastError( WSANO_RECOVERY
);
1182 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1184 WSASetLastError( WSANO_RECOVERY
);
1185 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1186 return NULL
; /* Can't get system directory */
1189 strncat(SystemDirectory
,
1190 ServicesFileLocation
,
1193 ServicesFile
= CreateFileA(SystemDirectory
,
1198 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1201 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1203 WSASetLastError( WSANO_RECOVERY
);
1207 /* Scan the services file ...
1209 * We will be share the buffer on the lines. If the line does not fit in
1210 * the buffer, then moving it to the beginning of the buffer and read
1211 * the remnants of line from file.
1215 ReadFile(ServicesFile
,
1217 sizeof( ServiceDBData
) - 1,
1219 ThisLine
= NextLine
= ServiceDBData
;
1220 EndValid
= ServiceDBData
+ ReadSize
;
1221 ServiceDBData
[sizeof(ServiceDBData
) - 1] = '\0';
1225 for(; *NextLine
!= '\r' && *NextLine
!= '\n'; NextLine
++)
1227 if(NextLine
== EndValid
)
1229 int LineLen
= NextLine
- ThisLine
;
1231 if(ThisLine
== ServiceDBData
)
1233 WS_DbgPrint(MIN_TRACE
,("Line too long"));
1234 WSASetLastError( WSANO_RECOVERY
);
1238 memmove(ServiceDBData
, ThisLine
, LineLen
);
1240 ReadFile(ServicesFile
, ServiceDBData
+ LineLen
,
1241 sizeof( ServiceDBData
)-1 - LineLen
,
1244 EndValid
= ServiceDBData
+ LineLen
+ ReadSize
;
1245 NextLine
= ServiceDBData
+ LineLen
;
1246 ThisLine
= ServiceDBData
;
1248 if(!ReadSize
) break;
1253 Comment
= strchr( ThisLine
, '#' );
1254 if( Comment
) *Comment
= '\0'; /* Terminate at comment start */
1256 if(DecodeServEntFromString(ThisLine
,
1261 WS2_INTERNAL_MAX_ALIAS
) &&
1262 !strcmp( ServiceName
, name
) &&
1263 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1266 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1268 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1269 (NextLine
- ThisLine
);
1273 ThisLine
= NextLine
;
1276 /* This we'll do no matter what */
1277 CloseHandle( ServicesFile
);
1281 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1282 WSASetLastError( WSANO_DATA
);
1286 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1288 /* Free previous getservbyname buffer, allocate bigger */
1289 if( p
->Getservbyname
)
1290 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1291 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1292 if( !p
->Getservbyname
)
1294 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1296 WSASetLastError( WSATRY_AGAIN
);
1299 p
->Getservbyname
->Size
= SizeNeeded
;
1303 memmove(p
->Getservbyname
->Data
,
1305 NextLine
- ThisLine
);
1307 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1308 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1309 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1313 for( i
= 0; Aliases
[i
]; i
++ )
1315 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1316 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1319 memcpy(p
->Getservbyname
,
1323 /* Create the struct proper */
1324 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1325 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1326 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1327 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1329 return &p
->Getservbyname
->ServerEntry
;
1338 getservbyport(IN INT port
,
1339 IN CONST CHAR FAR
* proto
)
1342 HANDLE ServicesFile
;
1343 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1344 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1345 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1346 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1347 ProtocolStr
= 0, Comment
= 0;
1348 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1349 UINT i
,SizeNeeded
= 0,
1350 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1351 DWORD ReadSize
= 0, ValidData
= 0;
1352 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1356 WSASetLastError( WSANOTINITIALISED
);
1362 WSASetLastError( WSANO_RECOVERY
);
1366 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1368 WSASetLastError( WSANO_RECOVERY
);
1369 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1370 return NULL
; /* Can't get system directory */
1373 strncat(SystemDirectory
,
1374 ServicesFileLocation
,
1377 ServicesFile
= CreateFileA(SystemDirectory
,
1382 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1385 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1387 WSASetLastError( WSANO_RECOVERY
);
1391 /* Scan the services file ...
1393 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1394 * contain a full line, then we will try to read more.
1396 * We fall from the loop if the buffer does not have a line terminator.
1401 ReadFile(ServicesFile
,
1402 ServiceDBData
+ ValidData
,
1403 sizeof( ServiceDBData
) - ValidData
,
1406 ValidData
+= ReadSize
;
1408 NextLine
= ThisLine
= ServiceDBData
;
1410 /* Find the beginning of the next line */
1411 while( NextLine
< ServiceDBData
+ ValidData
&&
1412 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1414 /* Zero and skip, so we can treat what we have as a string */
1415 if( NextLine
> ServiceDBData
+ ValidData
)
1418 *NextLine
= 0; NextLine
++;
1420 Comment
= strchr( ThisLine
, '#' );
1421 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1423 if(DecodeServEntFromString(ThisLine
,
1428 WS2_INTERNAL_MAX_ALIAS
) &&
1429 (htons(atoi( PortNumberStr
)) == port
) &&
1430 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1433 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1436 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1437 (NextLine
- ThisLine
);
1441 /* Get rid of everything we read so far */
1442 while( NextLine
<= ServiceDBData
+ ValidData
&&
1443 isspace( *NextLine
) )
1448 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1449 ServiceDBData
+ ValidData
- NextLine
));
1451 memmove(ServiceDBData
,
1453 ServiceDBData
+ ValidData
- NextLine
);
1454 ValidData
-= NextLine
- ServiceDBData
;
1455 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1458 /* This we'll do no matter what */
1459 CloseHandle( ServicesFile
);
1463 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1464 WSASetLastError( WSANO_DATA
);
1468 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1470 /* Free previous getservbyport buffer, allocate bigger */
1471 if( p
->Getservbyport
)
1472 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1473 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1476 if( !p
->Getservbyport
)
1478 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1480 WSASetLastError( WSATRY_AGAIN
);
1483 p
->Getservbyport
->Size
= SizeNeeded
;
1486 memmove(p
->Getservbyport
->Data
,
1488 NextLine
- ThisLine
);
1490 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1491 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1492 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1493 PortNumberStr
, ProtocolStr
));
1495 for( i
= 0; Aliases
[i
]; i
++ )
1497 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1498 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1501 memcpy(p
->Getservbyport
,Aliases
,sizeof(Aliases
));
1503 /* Create the struct proper */
1504 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1505 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1506 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1507 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1509 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1511 return &p
->Getservbyport
->ServerEntry
;
1521 inet_addr(IN CONST CHAR FAR
* cp
)
1523 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1525 * cp = Pointer to string with address to convert
1527 * Binary representation of IPv4 address, or INADDR_NONE
1538 WSASetLastError(WSAEFAULT
);
1545 if (strcmp(p
, " ") == 0)
1548 for (i
= 0; i
<= 3; i
++)
1550 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1570 inet_ntoa(IN IN_ADDR in
)
1575 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1576 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1578 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1581 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1584 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1588 return (CHAR FAR
*)p
;
1597 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1599 struct addrinfo
*next
, *cur
;
1603 next
= cur
->ai_next
;
1605 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1606 if (cur
->ai_canonname
)
1607 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1608 HeapFree(GetProcessHeap(), 0, cur
);
1615 new_addrinfo(struct addrinfo
*prev
)
1617 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1619 prev
->ai_next
= ret
;
1628 getaddrinfo(const char FAR
* nodename
,
1629 const char FAR
* servname
,
1630 const struct addrinfo FAR
* hints
,
1631 struct addrinfo FAR
* FAR
* res
)
1633 struct addrinfo
*ret
= NULL
, *ai
;
1639 DNS_STATUS dns_status
;
1640 PDNS_RECORD dp
, currdns
;
1641 struct sockaddr_in
*sin
;
1645 if (nodename
== NULL
&& servname
== NULL
)
1646 return WSAHOST_NOT_FOUND
;
1648 if (!WSAINITIALIZED
)
1649 return WSANOTINITIALISED
;
1653 /* converting port number */
1654 port
= strtoul(servname
, NULL
, 10);
1655 /* service name was specified? */
1658 /* protocol was specified? */
1659 if (hints
&& hints
->ai_protocol
)
1661 pent
= getprotobynumber(hints
->ai_protocol
);
1664 proto
= pent
->p_name
;
1668 se
= getservbyname(servname
, proto
);
1670 return WSATYPE_NOT_FOUND
;
1681 /* Is it an IPv6 address? */
1682 if (strstr(nodename
, ":"))
1683 return WSAHOST_NOT_FOUND
;
1685 /* Is it an IPv4 address? */
1686 addr
= inet_addr(nodename
);
1687 if (addr
!= INADDR_NONE
)
1689 ai
= new_addrinfo(NULL
);
1690 ai
->ai_family
= PF_INET
;
1691 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1692 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1693 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1694 sin
->sin_family
= AF_INET
;
1695 sin
->sin_port
= port
;
1696 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1699 if (ai
->ai_socktype
== 0)
1700 ai
->ai_socktype
= hints
->ai_socktype
;
1701 if (ai
->ai_protocol
== 0)
1702 ai
->ai_protocol
= hints
->ai_protocol
;
1708 /* resolving host name */
1709 dns_status
= DnsQuery_A(nodename
,
1713 /* extra dns servers */ &dp
,
1716 if (dns_status
== 0)
1719 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1721 /* accept only A records */
1722 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1724 ai
= new_addrinfo(ai
);
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
*)ret
->ai_addr
;
1731 sin
->sin_family
= AF_INET
;
1732 sin
->sin_port
= port
;
1733 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1736 if (ai
->ai_socktype
== 0)
1737 ai
->ai_socktype
= hints
->ai_socktype
;
1738 if (ai
->ai_protocol
== 0)
1739 ai
->ai_protocol
= hints
->ai_protocol
;
1742 DnsRecordListFree(dp
, DnsFreeRecordList
);
1748 ai
= new_addrinfo(NULL
);
1749 ai
->ai_family
= PF_INET
;
1750 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1751 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1752 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1753 sin
->sin_family
= AF_INET
;
1754 sin
->sin_port
= port
;
1757 if (!(hints
->ai_flags
& AI_PASSIVE
))
1759 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1760 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1761 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1762 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1764 if (ai
->ai_socktype
== 0)
1765 ai
->ai_socktype
= hints
->ai_socktype
;
1766 if (ai
->ai_protocol
== 0)
1767 ai
->ai_protocol
= hints
->ai_protocol
;
1773 return WSAHOST_NOT_FOUND
;
1775 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1778 return WSAEAFNOSUPPORT
;