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;
1176 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1177 UINT i
,SizeNeeded
= 0,
1178 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1179 DWORD ReadSize
= 0, ValidData
= 0;
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 read up to BUFSIZ bytes per pass, until the buffer does not
1222 * contain a full line, then we will try to read more.
1224 * We fall from the loop if the buffer does not have a line terminator.
1229 ReadFile(ServicesFile
,
1230 ServiceDBData
+ ValidData
,
1231 sizeof( ServiceDBData
) - ValidData
,
1235 ValidData
+= ReadSize
;
1237 NextLine
= ThisLine
= ServiceDBData
;
1239 /* Find the beginning of the next line */
1240 while(NextLine
< ServiceDBData
+ ValidData
&&
1241 *NextLine
!= '\r' && *NextLine
!= '\n' )
1246 /* Zero and skip, so we can treat what we have as a string */
1247 if( NextLine
> ServiceDBData
+ ValidData
)
1250 *NextLine
= 0; NextLine
++;
1252 Comment
= strchr( ThisLine
, '#' );
1253 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1255 if(DecodeServEntFromString(ThisLine
,
1260 WS2_INTERNAL_MAX_ALIAS
) &&
1261 !strcmp( ServiceName
, name
) &&
1262 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1265 WS_DbgPrint(MAX_TRACE
,("Found the service entry.\n"));
1267 SizeNeeded
= sizeof(WINSOCK_GETSERVBYNAME_CACHE
) +
1268 (NextLine
- ThisLine
);
1272 /* Get rid of everything we read so far */
1273 while( NextLine
<= ServiceDBData
+ ValidData
&&
1274 isspace( *NextLine
) )
1279 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1280 ServiceDBData
+ ValidData
- NextLine
));
1282 memmove(ServiceDBData
,
1284 ServiceDBData
+ ValidData
- NextLine
);
1285 ValidData
-= NextLine
- ServiceDBData
;
1286 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1289 /* This we'll do no matter what */
1290 CloseHandle( ServicesFile
);
1294 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1295 WSASetLastError( WSANO_DATA
);
1299 if( !p
->Getservbyname
|| p
->Getservbyname
->Size
< SizeNeeded
)
1301 /* Free previous getservbyname buffer, allocate bigger */
1302 if( p
->Getservbyname
)
1303 HeapFree(GlobalHeap
, 0, p
->Getservbyname
);
1304 p
->Getservbyname
= HeapAlloc(GlobalHeap
, 0, SizeNeeded
);
1305 if( !p
->Getservbyname
)
1307 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1309 WSASetLastError( WSATRY_AGAIN
);
1312 p
->Getservbyname
->Size
= SizeNeeded
;
1316 memmove(p
->Getservbyname
->Data
,
1318 NextLine
- ThisLine
);
1320 ADJ_PTR(ServiceName
,ThisLine
,p
->Getservbyname
->Data
);
1321 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyname
->Data
);
1322 WS_DbgPrint(MAX_TRACE
, ("ServiceName: %s, Protocol: %s\n",
1326 for( i
= 0; Aliases
[i
]; i
++ )
1328 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyname
->Data
);
1329 WS_DbgPrint(MAX_TRACE
,("Aliase %d: %s\n", i
, Aliases
[i
]));
1332 memcpy(p
->Getservbyname
,
1336 /* Create the struct proper */
1337 p
->Getservbyname
->ServerEntry
.s_name
= ServiceName
;
1338 p
->Getservbyname
->ServerEntry
.s_aliases
= p
->Getservbyname
->Aliases
;
1339 p
->Getservbyname
->ServerEntry
.s_port
= htons(atoi(PortNumberStr
));
1340 p
->Getservbyname
->ServerEntry
.s_proto
= ProtocolStr
;
1342 return &p
->Getservbyname
->ServerEntry
;
1351 getservbyport(IN INT port
,
1352 IN CONST CHAR FAR
* proto
)
1355 HANDLE ServicesFile
;
1356 CHAR ServiceDBData
[BUFSIZ
] = { 0 };
1357 PCHAR SystemDirectory
= ServiceDBData
; /* Reuse this stack space */
1358 PCHAR ServicesFileLocation
= "\\drivers\\etc\\services";
1359 PCHAR ThisLine
= 0, NextLine
= 0, ServiceName
= 0, PortNumberStr
= 0,
1360 ProtocolStr
= 0, Comment
= 0;
1361 PCHAR Aliases
[WS2_INTERNAL_MAX_ALIAS
] = { 0 };
1362 UINT i
,SizeNeeded
= 0,
1363 SystemDirSize
= sizeof(ServiceDBData
) - 1;
1364 DWORD ReadSize
= 0, ValidData
= 0;
1365 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
1369 WSASetLastError( WSANOTINITIALISED
);
1375 WSASetLastError( WSANO_RECOVERY
);
1379 if( !GetSystemDirectoryA( SystemDirectory
, SystemDirSize
) )
1381 WSASetLastError( WSANO_RECOVERY
);
1382 WS_DbgPrint(MIN_TRACE
, ("Could not get windows system directory.\n"));
1383 return NULL
; /* Can't get system directory */
1386 strncat(SystemDirectory
,
1387 ServicesFileLocation
,
1390 ServicesFile
= CreateFileA(SystemDirectory
,
1395 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,
1398 if( ServicesFile
== INVALID_HANDLE_VALUE
)
1400 WSASetLastError( WSANO_RECOVERY
);
1404 /* Scan the services file ...
1406 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1407 * contain a full line, then we will try to read more.
1409 * We fall from the loop if the buffer does not have a line terminator.
1414 ReadFile(ServicesFile
,
1415 ServiceDBData
+ ValidData
,
1416 sizeof( ServiceDBData
) - ValidData
,
1419 ValidData
+= ReadSize
;
1421 NextLine
= ThisLine
= ServiceDBData
;
1423 /* Find the beginning of the next line */
1424 while( NextLine
< ServiceDBData
+ ValidData
&&
1425 *NextLine
!= '\r' && *NextLine
!= '\n' ) NextLine
++;
1427 /* Zero and skip, so we can treat what we have as a string */
1428 if( NextLine
> ServiceDBData
+ ValidData
)
1431 *NextLine
= 0; NextLine
++;
1433 Comment
= strchr( ThisLine
, '#' );
1434 if( Comment
) *Comment
= 0; /* Terminate at comment start */
1436 if(DecodeServEntFromString(ThisLine
,
1441 WS2_INTERNAL_MAX_ALIAS
) &&
1442 (htons(atoi( PortNumberStr
)) == port
) &&
1443 (proto
? !strcmp( ProtocolStr
, proto
) : TRUE
) )
1446 WS_DbgPrint(MAX_TRACE
,("Found the port entry.\n"));
1449 SizeNeeded
= sizeof(WINSOCK_GETSERVBYPORT_CACHE
) +
1450 (NextLine
- ThisLine
);
1454 /* Get rid of everything we read so far */
1455 while( NextLine
<= ServiceDBData
+ ValidData
&&
1456 isspace( *NextLine
) )
1461 WS_DbgPrint(MAX_TRACE
,("About to move %d chars\n",
1462 ServiceDBData
+ ValidData
- NextLine
));
1464 memmove(ServiceDBData
,
1466 ServiceDBData
+ ValidData
- NextLine
);
1467 ValidData
-= NextLine
- ServiceDBData
;
1468 WS_DbgPrint(MAX_TRACE
,("Valid bytes: %d\n", ValidData
));
1471 /* This we'll do no matter what */
1472 CloseHandle( ServicesFile
);
1476 WS_DbgPrint(MAX_TRACE
,("Not found\n"));
1477 WSASetLastError( WSANO_DATA
);
1481 if( !p
->Getservbyport
|| p
->Getservbyport
->Size
< SizeNeeded
)
1483 /* Free previous getservbyport buffer, allocate bigger */
1484 if( p
->Getservbyport
)
1485 HeapFree(GlobalHeap
, 0, p
->Getservbyport
);
1486 p
->Getservbyport
= HeapAlloc(GlobalHeap
,
1489 if( !p
->Getservbyport
)
1491 WS_DbgPrint(MIN_TRACE
,("Couldn't allocate %d bytes\n",
1493 WSASetLastError( WSATRY_AGAIN
);
1496 p
->Getservbyport
->Size
= SizeNeeded
;
1499 memmove(p
->Getservbyport
->Data
,
1501 NextLine
- ThisLine
);
1503 ADJ_PTR(PortNumberStr
,ThisLine
,p
->Getservbyport
->Data
);
1504 ADJ_PTR(ProtocolStr
,ThisLine
,p
->Getservbyport
->Data
);
1505 WS_DbgPrint(MAX_TRACE
, ("Port Number: %s, Protocol: %s\n",
1506 PortNumberStr
, ProtocolStr
));
1508 for( i
= 0; Aliases
[i
]; i
++ )
1510 ADJ_PTR(Aliases
[i
],ThisLine
,p
->Getservbyport
->Data
);
1511 WS_DbgPrint(MAX_TRACE
,("Aliases %d: %s\n", i
, Aliases
[i
]));
1514 memcpy(p
->Getservbyport
,Aliases
,sizeof(Aliases
));
1516 /* Create the struct proper */
1517 p
->Getservbyport
->ServerEntry
.s_name
= ServiceName
;
1518 p
->Getservbyport
->ServerEntry
.s_aliases
= p
->Getservbyport
->Aliases
;
1519 p
->Getservbyport
->ServerEntry
.s_port
= port
;
1520 p
->Getservbyport
->ServerEntry
.s_proto
= ProtocolStr
;
1522 WS_DbgPrint(MID_TRACE
,("s_name: %s\n", ServiceName
));
1524 return &p
->Getservbyport
->ServerEntry
;
1534 inet_addr(IN CONST CHAR FAR
* cp
)
1536 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1538 * cp = Pointer to string with address to convert
1540 * Binary representation of IPv4 address, or INADDR_NONE
1551 WSASetLastError(WSAEFAULT
);
1558 if (strcmp(p
, " ") == 0)
1561 for (i
= 0; i
<= 3; i
++)
1563 u
+= (strtoul(p
, &p
, 0) << (i
* 8));
1583 inet_ntoa(IN IN_ADDR in
)
1588 p
= ((PWINSOCK_THREAD_BLOCK
)NtCurrentTeb()->WinSockData
)->Intoa
;
1589 _itoa(in
.S_un
.S_addr
& 0xFF, b
, 10);
1591 _itoa((in
.S_un
.S_addr
>> 8) & 0xFF, b
, 10);
1594 _itoa((in
.S_un
.S_addr
>> 16) & 0xFF, b
, 10);
1597 _itoa((in
.S_un
.S_addr
>> 24) & 0xFF, b
, 10);
1601 return (CHAR FAR
*)p
;
1610 freeaddrinfo(struct addrinfo
*pAddrInfo
)
1612 struct addrinfo
*next
, *cur
;
1616 next
= cur
->ai_next
;
1618 HeapFree(GetProcessHeap(), 0, cur
->ai_addr
);
1619 if (cur
->ai_canonname
)
1620 HeapFree(GetProcessHeap(), 0, cur
->ai_canonname
);
1621 HeapFree(GetProcessHeap(), 0, cur
);
1628 new_addrinfo(struct addrinfo
*prev
)
1630 struct addrinfo
*ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct addrinfo
));
1632 prev
->ai_next
= ret
;
1641 getaddrinfo(const char FAR
* nodename
,
1642 const char FAR
* servname
,
1643 const struct addrinfo FAR
* hints
,
1644 struct addrinfo FAR
* FAR
* res
)
1646 struct addrinfo
*ret
= NULL
, *ai
;
1652 DNS_STATUS dns_status
;
1653 PDNS_RECORD dp
, currdns
;
1654 struct sockaddr_in
*sin
;
1658 if (nodename
== NULL
&& servname
== NULL
)
1659 return WSAHOST_NOT_FOUND
;
1661 if (!WSAINITIALIZED
)
1662 return WSANOTINITIALISED
;
1666 /* converting port number */
1667 port
= strtoul(servname
, NULL
, 10);
1668 /* service name was specified? */
1671 /* protocol was specified? */
1672 if (hints
&& hints
->ai_protocol
)
1674 pent
= getprotobynumber(hints
->ai_protocol
);
1677 proto
= pent
->p_name
;
1681 se
= getservbyname(servname
, proto
);
1683 return WSATYPE_NOT_FOUND
;
1694 /* Is it an IPv6 address? */
1695 if (strstr(nodename
, ":"))
1696 return WSAHOST_NOT_FOUND
;
1698 /* Is it an IPv4 address? */
1699 addr
= inet_addr(nodename
);
1700 if (addr
!= INADDR_NONE
)
1702 ai
= new_addrinfo(NULL
);
1703 ai
->ai_family
= PF_INET
;
1704 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1705 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1706 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1707 sin
->sin_family
= AF_INET
;
1708 sin
->sin_port
= port
;
1709 RtlCopyMemory(&sin
->sin_addr
, &addr
, sizeof(sin
->sin_addr
));
1712 if (ai
->ai_socktype
== 0)
1713 ai
->ai_socktype
= hints
->ai_socktype
;
1714 if (ai
->ai_protocol
== 0)
1715 ai
->ai_protocol
= hints
->ai_protocol
;
1721 /* resolving host name */
1722 dns_status
= DnsQuery_A(nodename
,
1726 /* extra dns servers */ &dp
,
1729 if (dns_status
== 0)
1732 for (currdns
= dp
; currdns
; currdns
= currdns
->pNext
)
1734 /* accept only A records */
1735 if (currdns
->wType
!= DNS_TYPE_A
) continue;
1737 ai
= new_addrinfo(ai
);
1740 ai
->ai_family
= PF_INET
;
1741 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1742 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1743 sin
= (struct sockaddr_in
*)ret
->ai_addr
;
1744 sin
->sin_family
= AF_INET
;
1745 sin
->sin_port
= port
;
1746 RtlCopyMemory(&sin
->sin_addr
, &currdns
->Data
.A
.IpAddress
, sizeof(sin
->sin_addr
));
1749 if (ai
->ai_socktype
== 0)
1750 ai
->ai_socktype
= hints
->ai_socktype
;
1751 if (ai
->ai_protocol
== 0)
1752 ai
->ai_protocol
= hints
->ai_protocol
;
1755 DnsRecordListFree(dp
, DnsFreeRecordList
);
1761 ai
= new_addrinfo(NULL
);
1762 ai
->ai_family
= PF_INET
;
1763 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
1764 ai
->ai_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ai
->ai_addrlen
);
1765 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1766 sin
->sin_family
= AF_INET
;
1767 sin
->sin_port
= port
;
1770 if (!(hints
->ai_flags
& AI_PASSIVE
))
1772 sin
->sin_addr
.S_un
.S_un_b
.s_b1
= 127;
1773 sin
->sin_addr
.S_un
.S_un_b
.s_b2
= 0;
1774 sin
->sin_addr
.S_un
.S_un_b
.s_b3
= 0;
1775 sin
->sin_addr
.S_un
.S_un_b
.s_b4
= 1;
1777 if (ai
->ai_socktype
== 0)
1778 ai
->ai_socktype
= hints
->ai_socktype
;
1779 if (ai
->ai_protocol
== 0)
1780 ai
->ai_protocol
= hints
->ai_protocol
;
1786 return WSAHOST_NOT_FOUND
;
1788 if (hints
&& hints
->ai_family
!= PF_UNSPEC
&& hints
->ai_family
!= PF_INET
)
1791 return WSAEAFNOSUPPORT
;