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
)
36 CHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
39 if (!lpsaAddress
) return SOCKET_ERROR
;
40 if (!lpszAddressString
|| !lpdwAddressStringLength
) return SOCKET_ERROR
;
42 switch(lpsaAddress
->sa_family
)
45 if (dwAddressLength
< sizeof(SOCKADDR_IN
)) return SOCKET_ERROR
;
46 sprintf( buffer
, "%u.%u.%u.%u:%u",
47 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 24 & 0xff),
48 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 16 & 0xff),
49 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) >> 8 & 0xff),
50 (unsigned int)(ntohl( ((SOCKADDR_IN
*)lpsaAddress
)->sin_addr
.s_addr
) & 0xff),
51 ntohs( ((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) );
53 p
= strchr( buffer
, ':' );
54 if (!((SOCKADDR_IN
*)lpsaAddress
)->sin_port
) *p
= 0;
57 WSASetLastError(WSAEINVAL
);
61 size
= strlen( buffer
) + 1;
63 if (*lpdwAddressStringLength
< size
)
65 *lpdwAddressStringLength
= size
;
66 WSASetLastError(WSAEFAULT
);
70 *lpdwAddressStringLength
= size
;
71 strcpy( lpszAddressString
, buffer
);
81 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress
,
82 IN DWORD dwAddressLength
,
83 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
84 OUT LPWSTR lpszAddressString
,
85 IN OUT LPDWORD lpdwAddressStringLength
)
89 WCHAR buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
92 size
= *lpdwAddressStringLength
;
93 ret
= WSAAddressToStringA(lpsaAddress
, dwAddressLength
, NULL
, bufAddr
, &size
);
97 MultiByteToWideChar( CP_ACP
, 0, bufAddr
, size
, buffer
, sizeof( buffer
)/sizeof(WCHAR
));
99 if (*lpdwAddressStringLength
< size
)
101 *lpdwAddressStringLength
= size
;
102 WSASetLastError(WSAEFAULT
);
106 *lpdwAddressStringLength
= size
;
107 lstrcpyW( lpszAddressString
, buffer
);
117 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength
,
118 OUT LPWSANAMESPACE_INFOA lpnspBuffer
)
122 WSASetLastError(WSASYSCALLFAILURE
);
132 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength
,
133 OUT LPWSANAMESPACE_INFOW lpnspBuffer
)
137 WSASetLastError(WSASYSCALLFAILURE
);
147 WSAGetServiceClassInfoA(IN LPGUID lpProviderId
,
148 IN LPGUID lpServiceClassId
,
149 IN OUT LPDWORD lpdwBufferLength
,
150 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo
)
154 WSASetLastError(WSASYSCALLFAILURE
);
164 WSAGetServiceClassInfoW(IN LPGUID lpProviderId
,
165 IN LPGUID lpServiceClassId
,
166 IN OUT LPDWORD lpdwBufferLength
,
167 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
171 WSASetLastError(WSASYSCALLFAILURE
);
181 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId
,
182 OUT LPSTR lpszServiceClassName
,
183 IN OUT LPDWORD lpdwBufferLength
)
187 WSASetLastError(WSASYSCALLFAILURE
);
197 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId
,
198 OUT LPWSTR lpszServiceClassName
,
199 IN OUT LPDWORD lpdwBufferLength
)
203 WSASetLastError(WSASYSCALLFAILURE
);
213 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo
)
217 WSASetLastError(WSASYSCALLFAILURE
);
227 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo
)
231 WSASetLastError(WSASYSCALLFAILURE
);
241 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions
,
242 IN DWORD dwControlFlags
,
243 OUT LPHANDLE lphLookup
)
247 WSASetLastError(WSASYSCALLFAILURE
);
257 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions
,
258 IN DWORD dwControlFlags
,
259 OUT LPHANDLE lphLookup
)
263 WSASetLastError(WSASYSCALLFAILURE
);
273 WSALookupServiceEnd(IN HANDLE hLookup
)
277 WSASetLastError(WSASYSCALLFAILURE
);
287 WSALookupServiceNextA(IN HANDLE hLookup
,
288 IN DWORD dwControlFlags
,
289 IN OUT LPDWORD lpdwBufferLength
,
290 OUT LPWSAQUERYSETA lpqsResults
)
294 WSASetLastError(WSASYSCALLFAILURE
);
304 WSALookupServiceNextW(IN HANDLE hLookup
,
305 IN DWORD dwControlFlags
,
306 IN OUT LPDWORD lpdwBufferLength
,
307 OUT LPWSAQUERYSETW lpqsResults
)
311 WSASetLastError(WSASYSCALLFAILURE
);
321 WSARemoveServiceClass(IN LPGUID lpServiceClassId
)
325 WSASetLastError(WSASYSCALLFAILURE
);
335 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo
,
336 IN WSAESETSERVICEOP essOperation
,
337 IN DWORD dwControlFlags
)
341 WSASetLastError(WSASYSCALLFAILURE
);
351 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo
,
352 IN WSAESETSERVICEOP essOperation
,
353 IN DWORD dwControlFlags
)
357 WSASetLastError(WSASYSCALLFAILURE
);
367 WSAStringToAddressA(IN LPSTR AddressString
,
368 IN INT AddressFamily
,
369 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
370 OUT LPSOCKADDR lpAddress
,
371 IN OUT LPINT lpAddressLength
)
375 LPWSAPROTOCOL_INFOW lpProtoInfoW
= NULL
;
377 len
= MultiByteToWideChar(CP_ACP
,
384 szTemp
= HeapAlloc(GetProcessHeap(),
386 len
* sizeof(WCHAR
));
388 MultiByteToWideChar(CP_ACP
,
397 len
= WSAPROTOCOL_LEN
+1;
398 lpProtoInfoW
= HeapAlloc(GetProcessHeap(),
400 len
* sizeof(WCHAR
) );
404 sizeof(LPWSAPROTOCOL_INFOA
));
406 MultiByteToWideChar(CP_ACP
,
408 lpProtocolInfo
->szProtocol
,
410 lpProtoInfoW
->szProtocol
,
414 ret
= WSAStringToAddressW(szTemp
,
420 HeapFree(GetProcessHeap(),
425 HeapFree(GetProcessHeap(),
429 WSASetLastError(ret
);
440 WSAStringToAddressW(IN LPWSTR AddressString
,
441 IN INT AddressFamily
,
442 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
443 OUT LPSOCKADDR lpAddress
,
444 IN OUT LPINT lpAddressLength
)
450 SOCKADDR_IN
*sockaddr
;
452 if (!lpAddressLength
|| !lpAddress
|| !AddressString
)
454 WSASetLastError(WSAEINVAL
);
458 sockaddr
= (SOCKADDR_IN
*) lpAddress
;
460 /* Set right adress family */
461 if (lpProtocolInfo
!=NULL
)
462 sockaddr
->sin_family
= lpProtocolInfo
->iAddressFamily
;
464 else sockaddr
->sin_family
= AddressFamily
;
467 if (AddressFamily
== AF_INET
)
469 if (*lpAddressLength
< (INT
)sizeof(SOCKADDR_IN
))
471 *lpAddressLength
= sizeof(SOCKADDR_IN
);
476 // translate ip string to ip
478 /* rest sockaddr.sin_addr.s_addr
479 for we need to be sure it is zero when we come to while */
480 memset(lpAddress
,0,sizeof(SOCKADDR_IN
));
482 /* Set right adress family */
483 sockaddr
->sin_family
= AF_INET
;
485 /* Get port number */
486 pos
= wcscspn(AddressString
,L
":") + 1;
488 if (pos
< (int)wcslen(AddressString
))
489 sockaddr
->sin_port
= wcstol(&AddressString
[pos
],
494 sockaddr
->sin_port
= 0;
500 while (pos
< (int)wcslen(AddressString
))
502 inetaddr
= (inetaddr
<<8) + ((UCHAR
)wcstol(&AddressString
[pos
],
505 pos
+= wcscspn( &AddressString
[pos
],L
".") +1 ;
509 sockaddr
->sin_addr
.s_addr
= inetaddr
;
514 WSASetLastError(res
);
519 void check_hostent(struct hostent
**he
)
521 struct hostent
*new_he
;
523 WS_DbgPrint(MID_TRACE
,("*he: %x\n",*he
));
527 new_he
= HeapAlloc(GlobalHeap
,
529 sizeof(struct hostent
) + MAX_HOSTNAME_LEN
+ 1);
531 new_he
->h_name
= (PCHAR
)(new_he
+ 1);
532 new_he
->h_aliases
= 0;
533 new_he
->h_addrtype
= 0; // AF_INET
534 new_he
->h_length
= 0; // sizeof(in_addr)
535 new_he
->h_addr_list
= HeapAlloc(GlobalHeap
,
539 RtlZeroMemory(new_he
->h_addr_list
,
545 void populate_hostent(struct hostent
*he
, char* name
, DNS_A_DATA addr
)
549 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
550 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
556 if( !he
->h_aliases
) {
557 he
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
558 he
->h_aliases
[0] = 0;
560 he
->h_addrtype
= AF_INET
;
561 he
->h_length
= sizeof(IN_ADDR
); //sizeof(struct in_addr);
563 if( he
->h_addr_list
[0] )
570 he
->h_addr_list
[0] = HeapAlloc(GlobalHeap
,
572 MAX_HOSTNAME_LEN
+ 1);
574 WS_DbgPrint(MID_TRACE
,("he->h_addr_list[0] %x\n", he
->h_addr_list
[0]));
576 RtlCopyMemory(he
->h_addr_list
[0],
577 (char*)&addr
.IpAddress
,
578 sizeof(addr
.IpAddress
));
580 he
->h_addr_list
[1] = 0;
584 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
585 void free_hostent(struct hostent
*he
)
593 next
= he
->h_aliases
[0];
594 while(next
) { HFREE(next
); next
++; }
598 next
= he
->h_addr_list
[0];
599 while(next
) { HFREE(next
); next
++; }
601 HFREE(he
->h_addr_list
);
602 HFREE(he
->h_aliases
);
607 /* WinSock 1.1 compatible name resolution APIs */
614 gethostbyaddr(IN CONST CHAR FAR
* addr
,
620 return (LPHOSTENT
)NULL
;
624 Assumes rfc 1123 - adam *
626 addr[0] = inet_addr(name);
627 strcpy( hostname, name );
628 if(addr[0] == 0xffffffff) return NULL;
629 he.h_addr_list = (void *)addr;
630 he.h_name = hostname;
632 he.h_addrtype = AF_INET;
633 he.h_length = sizeof(addr);
637 From the MSDN Platform SDK: Windows Sockets 2
638 "The gethostbyname function cannot resolve IP address strings passed to it.
639 Such a request is treated exactly as if an unknown host name were passed."
642 Defferring to the the documented behaviour, rather than the unix behaviour
643 What if the hostname is in the HOSTS file? see getservbyname
648 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
649 /* see ws2_32.h, winsock2.h*/
650 /*getnetworkparameters - iphlp api */
654 servent -- w32api/include/winsock2.h
655 PWINSOCK_THREAD_BLOCK -- ws2_32.h
656 dllmain.c -- threadlocal memory allocation / deallocation
661 /* lib/adns/src/adns.h XXX */
671 #define h_addr h_addr_list[0]
681 struct hostent defined in w32api/include/winsock2.h
684 void free_servent(struct servent
* s
)
688 next
= s
->s_aliases
[0];
689 while(next
) { HFREE(next
); next
++; }
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
);
822 p
->Hostent
= HeapAlloc(GlobalHeap
, 0, sizeof(*p
->Hostent
));
825 WSASetLastError( WSATRY_AGAIN
);
830 p
->Hostent
->h_name
= HeapAlloc(GlobalHeap
, 0, strlen(DnsName
));
831 if( !p
->Hostent
->h_name
)
833 WSASetLastError( WSATRY_AGAIN
);
837 RtlCopyMemory(p
->Hostent
->h_name
,
841 p
->Hostent
->h_aliases
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
842 if( !p
->Hostent
->h_aliases
)
844 WSASetLastError( WSATRY_AGAIN
);
848 p
->Hostent
->h_aliases
[0] = 0;
850 if (strstr(AddressStr
, ":"))
852 DbgPrint("AF_INET6 NOT SUPPORTED!\n");
853 WSASetLastError(WSAEINVAL
);
857 p
->Hostent
->h_addrtype
= AF_INET
;
859 p
->Hostent
->h_addr_list
= HeapAlloc(GlobalHeap
, 0, sizeof(char *));
860 if( !p
->Hostent
->h_addr_list
)
862 WSASetLastError( WSATRY_AGAIN
);
866 Address
= inet_addr(AddressStr
);
867 if (Address
== INADDR_NONE
)
869 WSASetLastError(WSAEINVAL
);
873 p
->Hostent
->h_addr_list
[0] = HeapAlloc(GlobalHeap
, 0, sizeof(Address
));
874 if( !p
->Hostent
->h_addr_list
[0] )
876 WSASetLastError( WSATRY_AGAIN
);
880 RtlCopyMemory(p
->Hostent
->h_addr_list
[0],
884 p
->Hostent
->h_length
= sizeof(Address
);
891 gethostbyname(IN CONST CHAR FAR
* name
)
900 typedef enum addr_type addr_type
;
904 DNS_STATUS dns_status
= {0};
905 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
907 PWINSOCK_THREAD_BLOCK p
;
912 p
= NtCurrentTeb()->WinSockData
;
916 WSASetLastError( WSANOTINITIALISED
);
920 check_hostent(&p
->Hostent
); /*XXX alloc_hostent*/
922 /* Hostname NULL - behave like gethostname */
925 ret
= gethostname(p
->Hostent
->h_name
, MAX_HOSTNAME_LEN
);
931 WSASetLastError( WSAHOST_NOT_FOUND
); //WSANO_DATA ??
935 /* Is it an IPv6 address? */
936 found
= strstr(name
, ":");
943 /* Is it an IPv4 address? */
944 if (!isalpha(name
[0]))
950 addr
= GH_RFC1123_DNS
;
952 /* Broken out in case we want to get fancy later */
957 WSASetLastError(STATUS_NOT_IMPLEMENTED
);
962 WSASetLastError(WSAEFAULT
);
966 /* Note: If passed an IP address, MSDN says that gethostbyname()
967 treats it as an unknown host.
968 This is different from the unix implementation. Use inet_addr()
972 /* DNS_TYPE_A: include/WinDNS.h */
973 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
975 /* Look for the DNS name in the hosts file */
976 Hostent
= FindEntryInHosts(name
);
980 dns_status
= DnsQuery_A(name
,
984 /* extra dns servers */ &dp
,
989 //ASSERT(dp->wType == DNS_TYPE_A);
990 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
993 curr
!= NULL
&& curr
->wType
!= DNS_TYPE_A
;
996 WS_DbgPrint(MID_TRACE
,("wType: %i\n", curr
->wType
));
1002 WS_DbgPrint(MID_TRACE
,("populating hostent\n"));
1003 WS_DbgPrint(MID_TRACE
,("pName is (%s)\n", curr
->pName
));
1004 populate_hostent(p
->Hostent
, (PCHAR
)curr
->pName
, curr
->Data
.A
);
1005 DnsRecordListFree(dp
, DnsFreeRecordList
);
1010 DnsRecordListFree(dp
, DnsFreeRecordList
);
1014 WS_DbgPrint(MID_TRACE
,("Called DnsQuery, but host not found. Err: %i\n",
1016 WSASetLastError(WSAHOST_NOT_FOUND
);
1022 WSASetLastError(WSANO_RECOVERY
);
1027 WSASetLastError(WSANO_RECOVERY
);
1036 gethostname(OUT CHAR FAR
* name
,
1039 DWORD size
= namelen
;
1041 int ret
= GetComputerNameExA(ComputerNameDnsHostname
,
1046 WSASetLastError(WSAEFAULT
);
1047 return SOCKET_ERROR
;
1051 name
[namelen
-1] = '\0';
1058 * XXX arty -- Partial implementation pending a better one. This one will
1059 * do for normal purposes.#include <ws2_32.h>
1061 * Return the address of a static LPPROTOENT corresponding to the named
1062 * protocol. These structs aren't very interesting, so I'm not too ashamed
1063 * to have this function work on builtins for now.
1068 static CHAR
*no_aliases
= 0;
1069 static PROTOENT protocols
[] =
1071 {"icmp",&no_aliases
, IPPROTO_ICMP
},
1072 {"tcp", &no_aliases
, IPPROTO_TCP
},
1073 {"udp", &no_aliases
, IPPROTO_UDP
},
1079 getprotobyname(IN CONST CHAR FAR
* name
)
1082 for (i
= 0; protocols
[i
].p_name
; i
++)
1084 if (_stricmp(protocols
[i
].p_name
, name
) == 0)
1085 return &protocols
[i
];
1095 getprotobynumber(IN INT number
)
1098 for (i
= 0; protocols
[i
].p_name
; i
++)
1100 if (protocols
[i
].p_proto
== number
)
1101 return &protocols
[i
];
1106 #define SKIPWS(ptr,act) \
1107 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
1108 #define SKIPANDMARKSTR(ptr,act) \
1109 {while(*ptr && !isspace(*ptr)) ptr++; \
1110 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
1114 DecodeServEntFromString(IN PCHAR ServiceString
,
1115 OUT PCHAR
*ServiceName
,
1116 OUT PCHAR
*PortNumberStr
,
1117 OUT PCHAR
*ProtocolStr
,
1123 WS_DbgPrint(MAX_TRACE
, ("Parsing service ent [%s]\n", ServiceString
));
1125 SKIPWS(ServiceString
, return FALSE
);
1126 *ServiceName
= ServiceString
;
1127 SKIPANDMARKSTR(ServiceString
, return FALSE
);
1128 SKIPWS(ServiceString
, return FALSE
);
1129 *PortNumberStr
= ServiceString
;
1130 SKIPANDMARKSTR(ServiceString
, ;);
1132 while( *ServiceString
&& NAliases
< MaxAlias
- 1 )
1134 SKIPWS(ServiceString
, break);
1135 if( *ServiceString
)
1137 SKIPANDMARKSTR(ServiceString
, ;);
1138 if( strlen(ServiceString
) )
1140 WS_DbgPrint(MAX_TRACE
, ("Alias: %s\n", ServiceString
));
1141 *Aliases
++ = ServiceString
;
1148 *ProtocolStr
= strchr(*PortNumberStr
,'/');
1149 if( !*ProtocolStr
) return FALSE
;
1150 **ProtocolStr
= 0; (*ProtocolStr
)++;
1152 WS_DbgPrint(MAX_TRACE
, ("Parsing done: %s %s %s %d\n",
1153 *ServiceName
, *ProtocolStr
, *PortNumberStr
,
1159 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
1166 getservbyname(IN CONST CHAR FAR
* name
,
1167 IN CONST CHAR FAR
* proto
)
1170 HANDLE ServicesFile
;
1171 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1172 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1173 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1174 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1175 ProtocolStr
= 0, Comment
= 0, EndValid
;
1176 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1177 UINT i
,SizeNeeded
= 0,
1178 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1180 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1184 WSASetLastError( WSANOTINITIALISED
);
1190 WSASetLastError( WSANO_RECOVERY
);
1194 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1196 WSASetLastError( WSANO_RECOVERY
);
1197 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1198 return NULL
; /* Can't get system directory */
1201 strncat(SystemDirectory
,
1202 ServicesFileLocation
,
1205 ServicesFile
= CreateFileA(SystemDirectory
,
1210 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1213 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1215 WSASetLastError( WSANO_RECOVERY
);
1219 /* Scan the services file ...
1221 * We will be share the buffer on the lines. If the line does not fit in
1222 * the buffer, then moving it to the beginning of the buffer and read
1223 * the remnants of line from file.
1227 ReadFile(ServicesFile
,
1229 sizeof( ServiceDBData
) - 1,
1231 ThisLine
= NextLine
= ServiceDBData
;
1232 EndValid
= ServiceDBData
+ ReadSize
;
1233 ServiceDBData
[sizeof(ServiceDBData
) - 1] = '\0';
1237 for(; *NextLine
!= '\r' && *NextLine
!= '\n'; NextLine
++)
1239 if(NextLine
== EndValid
)
1241 int LineLen
= NextLine
- ThisLine
;
1243 if(ThisLine
== ServiceDBData
)
1245 WS_DbgPrint(MIN_TRACE
,("Line too long"));
1246 WSASetLastError( WSANO_RECOVERY
);
1250 memmove(ServiceDBData
, ThisLine
, LineLen
);
1252 ReadFile(ServicesFile
, ServiceDBData
+ LineLen
,
1253 sizeof( ServiceDBData
)-1 - LineLen
,
1256 EndValid
= ServiceDBData
+ LineLen
+ ReadSize
;
1257 NextLine
= ServiceDBData
+ LineLen
;
1258 ThisLine
= ServiceDBData
;
1260 if(!ReadSize
) break;
1265 Comment
= strchr( ThisLine
, '#' );
1266 if( Comment
) *Comment
= '\0'; /* Terminate at comment start */
1268 if(DecodeServEntFromString(ThisLine
,
1273 WS2_INTERNAL_MAX_ALIAS
) &&
1274 !strcmp( ServiceName
, name
) &&
1275 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1278 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1280 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1281 (NextLine
- ThisLine
);
1285 ThisLine
= NextLine
;
1288 /* This we'll do no matter what */
1289 CloseHandle( ServicesFile
);
1293 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1294 WSASetLastError( WSANO_DATA
);
1298 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1300 /* Free previous getservbyname buffer, allocate bigger */
1301 if( p
->Getservbyname
)
1302 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1303 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1304 if( !p
->Getservbyname
)
1306 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1308 WSASetLastError( WSATRY_AGAIN
);
1311 p
->Getservbyname
->Size
= SizeNeeded
;
1315 memmove(p
->Getservbyname
->Data
,
1317 NextLine
- ThisLine
);
1319 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1320 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1321 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1325 for( i
= 0; Aliases
[i
]; i
++ )
1327 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1328 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1331 memcpy(p
->Getservbyname
,
1335 /* Create the struct proper */
1336 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1337 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1338 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1339 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1341 return &p
->Getservbyname
->ServerEntry
;
1350 getservbyport(IN INT port
,
1351 IN CONST CHAR FAR
* proto
)
1354 HANDLE ServicesFile
;
1355 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1356 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1357 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1358 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1359 ProtocolStr
= 0, Comment
= 0;
1360 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1361 UINT i
,SizeNeeded
= 0,
1362 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1363 DWORD ReadSize
= 0, ValidData
= 0;
1364 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1368 WSASetLastError( WSANOTINITIALISED
);
1374 WSASetLastError( WSANO_RECOVERY
);
1378 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1380 WSASetLastError( WSANO_RECOVERY
);
1381 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1382 return NULL
; /* Can't get system directory */
1385 strncat(SystemDirectory
,
1386 ServicesFileLocation
,
1389 ServicesFile
= CreateFileA(SystemDirectory
,
1394 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1397 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1399 WSASetLastError( WSANO_RECOVERY
);
1403 /* Scan the services file ...
1405 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1406 * contain a full line, then we will try to read more.
1408 * We fall from the loop if the buffer does not have a line terminator.
1413 ReadFile(ServicesFile
,
1414 ServiceDBData
+ ValidData
,
1415 sizeof( ServiceDBData
) - ValidData
,
1418 ValidData
+= ReadSize
;
1420 NextLine
= ThisLine
= ServiceDBData
;
1422 /* Find the beginning of the next line */
1423 while( NextLine
< ServiceDBData
+ ValidData
&&
1424 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1426 /* Zero and skip, so we can treat what we have as a string */
1427 if( NextLine
> ServiceDBData
+ ValidData
)
1430 *NextLine
= 0; NextLine
++;
1432 Comment
= strchr( ThisLine
, '#' );
1433 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1435 if(DecodeServEntFromString(ThisLine
,
1440 WS2_INTERNAL_MAX_ALIAS
) &&
1441 (htons(atoi( PortNumberStr
)) == port
) &&
1442 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1445 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1448 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1449 (NextLine
- ThisLine
);
1453 /* Get rid of everything we read so far */
1454 while( NextLine
<= ServiceDBData
+ ValidData
&&
1455 isspace( *NextLine
) )
1460 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1461 ServiceDBData
+ ValidData
- NextLine
));
1463 memmove(ServiceDBData
,
1465 ServiceDBData
+ ValidData
- NextLine
);
1466 ValidData
-= NextLine
- ServiceDBData
;
1467 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1470 /* This we'll do no matter what */
1471 CloseHandle( ServicesFile
);
1475 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1476 WSASetLastError( WSANO_DATA
);
1480 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1482 /* Free previous getservbyport buffer, allocate bigger */
1483 if( p
->Getservbyport
)
1484 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1485 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1488 if( !p
->Getservbyport
)
1490 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1492 WSASetLastError( WSATRY_AGAIN
);
1495 p
->Getservbyport
->Size
= SizeNeeded
;
1498 memmove(p
->Getservbyport
->Data
,
1500 NextLine
- ThisLine
);
1502 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1503 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1504 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1505 PortNumberStr
, ProtocolStr
));
1507 for( i
= 0; Aliases
[i
]; i
++ )
1509 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1510 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1513 memcpy(p
->Getservbyport
,Aliases
,sizeof(Aliases
));
1515 /* Create the struct proper */
1516 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1517 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1518 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1519 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1521 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1523 return &p
->Getservbyport
->ServerEntry
;
1533 inet_addr(IN CONST CHAR FAR
* cp
)
1535 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1537 * cp = Pointer to string with address to convert
1539 * Binary representation of IPv4 address, or INADDR_NONE
1550 WSASetLastError(WSAEFAULT
);
1557 if (strcmp(p
, " ") == 0)
1560 for (i
= 0; i
<= 3; i
++)
1562 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1582 inet_ntoa(IN IN_ADDR in
)
1587 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1588 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1590 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1593 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1596 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1600 return (CHAR FAR
*)p
;
1609 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1611 struct addrinfo
*next
, *cur
;
1615 next
= cur
->ai_next
;
1617 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1618 if (cur
->ai_canonname
)
1619 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1620 HeapFree(GetProcessHeap(), 0, cur
);
1627 new_addrinfo(struct addrinfo
*prev
)
1629 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1631 prev
->ai_next
= ret
;
1640 getaddrinfo(const char FAR
* nodename
,
1641 const char FAR
* servname
,
1642 const struct addrinfo FAR
* hints
,
1643 struct addrinfo FAR
* FAR
* res
)
1645 struct addrinfo
*ret
= NULL
, *ai
;
1651 DNS_STATUS dns_status
;
1652 PDNS_RECORD dp
, currdns
;
1653 struct sockaddr_in
*sin
;
1657 if (nodename
== NULL
&& servname
== NULL
)
1658 return WSAHOST_NOT_FOUND
;
1660 if (!WSAINITIALIZED
)
1661 return WSANOTINITIALISED
;
1665 /* converting port number */
1666 port
= strtoul(servname
, NULL
, 10);
1667 /* service name was specified? */
1670 /* protocol was specified? */
1671 if (hints
&& hints
->ai_protocol
)
1673 pent
= getprotobynumber(hints
->ai_protocol
);
1676 proto
= pent
->p_name
;
1680 se
= getservbyname(servname
, proto
);
1682 return WSATYPE_NOT_FOUND
;
1693 /* Is it an IPv6 address? */
1694 if (strstr(nodename
, ":"))
1695 return WSAHOST_NOT_FOUND
;
1697 /* Is it an IPv4 address? */
1698 addr
= inet_addr(nodename
);
1699 if (addr
!= INADDR_NONE
)
1701 ai
= new_addrinfo(NULL
);
1702 ai
->ai_family
= PF_INET
;
1703 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1704 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1705 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1706 sin
->sin_family
= AF_INET
;
1707 sin
->sin_port
= port
;
1708 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1711 if (ai
->ai_socktype
== 0)
1712 ai
->ai_socktype
= hints
->ai_socktype
;
1713 if (ai
->ai_protocol
== 0)
1714 ai
->ai_protocol
= hints
->ai_protocol
;
1720 /* resolving host name */
1721 dns_status
= DnsQuery_A(nodename
,
1725 /* extra dns servers */ &dp
,
1728 if (dns_status
== 0)
1731 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1733 /* accept only A records */
1734 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1736 ai
= new_addrinfo(ai
);
1739 ai
->ai_family
= PF_INET
;
1740 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1741 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1742 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1743 sin
->sin_family
= AF_INET
;
1744 sin
->sin_port
= port
;
1745 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1748 if (ai
->ai_socktype
== 0)
1749 ai
->ai_socktype
= hints
->ai_socktype
;
1750 if (ai
->ai_protocol
== 0)
1751 ai
->ai_protocol
= hints
->ai_protocol
;
1754 DnsRecordListFree(dp
, DnsFreeRecordList
);
1760 ai
= new_addrinfo(NULL
);
1761 ai
->ai_family
= PF_INET
;
1762 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1763 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1764 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1765 sin
->sin_family
= AF_INET
;
1766 sin
->sin_port
= port
;
1769 if (!(hints
->ai_flags
& AI_PASSIVE
))
1771 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1772 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1773 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1774 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1776 if (ai
->ai_socktype
== 0)
1777 ai
->ai_socktype
= hints
->ai_socktype
;
1778 if (ai
->ai_protocol
== 0)
1779 ai
->ai_protocol
= hints
->ai_protocol
;
1785 return WSAHOST_NOT_FOUND
;
1787 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1790 return WSAEAFNOSUPPORT
;