7 #if (NTDDI_VERSION >= NTDDI_WIN2K)
14 #if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L
16 #define _WSPIAPI_STRCPY_S strcpy_s
17 #define _WSPIAPI_STRCAT_S strcat_s
21 #define _WSPIAPI_STRCPY_S(_Dst, _Size, _Src) strcpy((_Dst), (_Src))
22 #define _WSPIAPI_STRCAT_S(_Dst, _Size, _Src) strcat((_Dst), (_Src))
24 #endif /* defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L */
26 #define _WSPIAPI_STRNCPY_S(_Dst, _Size, _Src, _Count) strncpy((_Dst), (_Src), (_Count)); (_Dst)[(_Size) - 1] = 0 //FIXME
27 #define _WSPIAPI_SPRINTF_S_1(_Dst, _Size, _Format, _Arg1) sprintf((_Dst), (_Format), (_Arg1)) //FIXME
29 #if !defined(_WSPIAPI_COUNTOF)
31 #if !defined(__cplusplus)
32 #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
34 template <typename __CountofType
, size_t _N
>
35 char (&__wspiapi_countof_helper(__CountofType (&_Array
)[_N
]))[_N
];
36 #define _WSPIAPI_COUNTOF(_Array) sizeof(__wspiapi_countof_helper(_Array))
39 #endif /* !defined(_WSPIAPI_COUNTOF) */
41 #define WspiapiMalloc(tSize) calloc(1, (tSize))
42 #define WspiapiFree(p) free(p)
43 #define WspiapiSwap(a, b, c) {(c) = (a); (a) = (b); (b) = (c);}
44 #define getaddrinfo WspiapiGetAddrInfo
45 #define getnameinfo WspiapiGetNameInfo
46 #define freeaddrinfo WspiapiFreeAddrInfo
49 #define WSPIAPI_INLINE __inline
51 #define WSPIAPI_INLINE static inline
55 (WINAPI
*WSPIAPI_PGETADDRINFO
)(
56 IN
const char *nodename
,
57 IN
const char *servname
,
58 IN
const struct addrinfo
*hints
,
59 OUT
struct addrinfo
**res
);
62 (WINAPI
*WSPIAPI_PGETNAMEINFO
)(
63 IN
const struct sockaddr
*sa
,
72 (WINAPI
*WSPIAPI_PFREEADDRINFO
)(
73 IN
struct addrinfo
*ai
);
79 IN
const char *pszString
)
84 if (!pszString
) return(NULL
);
85 cchMemory
= strlen(pszString
) + 1;
86 pszMemory
= (char *) WspiapiMalloc(cchMemory
);
87 if (!pszMemory
) return(NULL
);
88 _WSPIAPI_STRCPY_S(pszMemory
, cchMemory
, pszString
);
95 WspiapiParseV4Address(
96 IN
const char *pszAddress
,
97 OUT PDWORD pdwAddress
)
100 const char *pcNext
= NULL
;
103 for (pcNext
= pszAddress
; *pcNext
!= '\0'; pcNext
++)
104 if (*pcNext
== '.') iCount
++;
105 if (iCount
!= 3) return FALSE
;
106 dwAddress
= inet_addr(pszAddress
);
107 if (dwAddress
== INADDR_NONE
) return FALSE
;
108 *pdwAddress
= dwAddress
;
121 struct addrinfo
*ptNew
;
122 struct sockaddr_in
*ptAddress
;
124 ptNew
= (struct addrinfo
*) WspiapiMalloc(sizeof(struct addrinfo
));
125 if (!ptNew
) return NULL
;
126 ptAddress
= (struct sockaddr_in
*) WspiapiMalloc(sizeof(struct sockaddr_in
));
131 ptAddress
->sin_family
= AF_INET
;
132 ptAddress
->sin_port
= wPort
;
133 ptAddress
->sin_addr
.s_addr
= dwAddress
;
134 ptNew
->ai_family
= PF_INET
;
135 ptNew
->ai_socktype
= iSocketType
;
136 ptNew
->ai_protocol
= iProtocol
;
137 ptNew
->ai_addrlen
= sizeof(struct sockaddr_in
);
138 ptNew
->ai_addr
= (struct sockaddr
*) ptAddress
;
147 IN
const char *pszNodeName
,
151 OUT
char pszAlias
[NI_MAXHOST
],
152 OUT
struct addrinfo
**pptResult
)
154 struct addrinfo
**pptNext
= pptResult
;
155 struct hostent
*ptHost
= NULL
;
161 ptHost
= gethostbyname(pszNodeName
);
163 if ((ptHost
->h_addrtype
== AF_INET
) && (ptHost
->h_length
== sizeof(struct in_addr
))) {
164 for (ppAddresses
= ptHost
->h_addr_list
; *ppAddresses
!= NULL
; ppAddresses
++) {
165 *pptNext
= WspiapiNewAddrInfo(iSocketType
, iProtocol
, wPort
, ((struct in_addr
*) *ppAddresses
)->s_addr
);
166 if (!*pptNext
) return EAI_MEMORY
;
167 pptNext
= &((*pptNext
)->ai_next
);
170 _WSPIAPI_STRNCPY_S(pszAlias
, NI_MAXHOST
, ptHost
->h_name
, NI_MAXHOST
- 1);
173 switch (WSAGetLastError()) {
174 case WSAHOST_NOT_FOUND
: return EAI_NONAME
;
175 case WSATRY_AGAIN
: return EAI_AGAIN
;
176 case WSANO_RECOVERY
: return EAI_FAIL
;
177 case WSANO_DATA
: return EAI_NODATA
;
178 default: return EAI_NONAME
;
186 IN
const char *pszNodeName
,
190 IN BOOL bAI_CANONNAME
,
191 OUT
struct addrinfo
**pptResult
)
195 char szFQDN1
[NI_MAXHOST
] = "";
196 char szFQDN2
[NI_MAXHOST
] = "";
197 char *pszName
= szFQDN1
;
198 char *pszAlias
= szFQDN2
;
199 char *pszScratch
= NULL
;
201 _WSPIAPI_STRNCPY_S(pszName
, NI_MAXHOST
, pszNodeName
, NI_MAXHOST
- 1);
203 iError
= WspiapiQueryDNS(pszNodeName
, iSocketType
, iProtocol
, wPort
, pszAlias
, pptResult
);
205 if (*pptResult
) break;
206 if ((!strlen(pszAlias
)) || (!strcmp(pszName
, pszAlias
)) || (++iAliasCount
== 16)) {
210 WspiapiSwap(pszName
, pszAlias
, pszScratch
);
212 if (!iError
&& bAI_CANONNAME
) {
213 (*pptResult
)->ai_canonname
= WspiapiStrdup(pszAlias
);
214 if (!(*pptResult
)->ai_canonname
) iError
= EAI_MEMORY
;
227 IN
struct addrinfo
*ptResult
)
229 struct addrinfo
*ptNext
= NULL
;
230 struct addrinfo
*ptNew
= NULL
;
232 for (ptNext
= ptResult
; ptNext
!= NULL
; ) {
233 ptNew
= WspiapiNewAddrInfo(SOCK_DGRAM
, ptNext
->ai_protocol
, wPort
,
234 ((struct sockaddr_in
*) ptNext
->ai_addr
)->sin_addr
.s_addr
);
236 ptNew
->ai_next
= ptNext
->ai_next
;
237 ptNext
->ai_next
= ptNew
;
238 ptNext
= ptNew
->ai_next
;
240 if (ptNext
!= NULL
) return EAI_MEMORY
;
248 WspiapiLegacyFreeAddrInfo(
249 IN
struct addrinfo
*ptHead
)
251 struct addrinfo
*ptNext
;
253 for (ptNext
= ptHead
; ptNext
!= NULL
; ptNext
= ptHead
) {
254 if (ptNext
->ai_canonname
) WspiapiFree(ptNext
->ai_canonname
);
255 if (ptNext
->ai_addr
) WspiapiFree(ptNext
->ai_addr
);
256 ptHead
= ptNext
->ai_next
;
264 WspiapiLegacyGetAddrInfo(
265 IN
const char *pszNodeName
,
266 IN
const char *pszServiceName
,
267 IN
const struct addrinfo
*ptHints
,
268 OUT
struct addrinfo
**pptResult
)
272 int iFamily
= PF_UNSPEC
;
277 struct servent
*ptService
= NULL
;
284 if ((!pszNodeName
) && (!pszServiceName
)) return EAI_NONAME
;
286 if ((ptHints
->ai_addrlen
!= 0) ||
287 (ptHints
->ai_canonname
!= NULL
) ||
288 (ptHints
->ai_addr
!= NULL
) ||
289 (ptHints
->ai_next
!= NULL
)) {
292 iFlags
= ptHints
->ai_flags
;
293 if ((iFlags
& AI_CANONNAME
) && !pszNodeName
) return EAI_BADFLAGS
;
294 iFamily
= ptHints
->ai_family
;
295 if ((iFamily
!= PF_UNSPEC
) && (iFamily
!= PF_INET
)) return EAI_FAMILY
;
296 iSocketType
= ptHints
->ai_socktype
;
297 if ((iSocketType
!= 0) &&
298 (iSocketType
!= SOCK_STREAM
) &&
299 (iSocketType
!= SOCK_DGRAM
) &&
300 (iSocketType
!= SOCK_RAW
))
302 iProtocol
= ptHints
->ai_protocol
;
304 if (pszServiceName
) {
305 wPort
= (WORD
) strtoul(pszServiceName
, &pc
, 10);
307 wPort
= wTcpPort
= wUdpPort
= htons(wPort
);
308 if (iSocketType
== 0) {
310 iSocketType
= SOCK_STREAM
;
314 if ((iSocketType
== 0) || (iSocketType
== SOCK_DGRAM
)) {
315 ptService
= getservbyname(pszServiceName
, "udp");
316 if (ptService
) wPort
= wUdpPort
= ptService
->s_port
;
318 if ((iSocketType
== 0) || (iSocketType
== SOCK_STREAM
)) {
319 ptService
= getservbyname(pszServiceName
, "tcp");
320 if (ptService
) wPort
= wTcpPort
= ptService
->s_port
;
322 if (wPort
== 0) return (iSocketType
? EAI_SERVICE
: EAI_NONAME
);
323 if (iSocketType
== 0) {
324 iSocketType
= (wTcpPort
) ? SOCK_STREAM
: SOCK_DGRAM
;
325 bClone
= (wTcpPort
&& wUdpPort
);
329 if ((!pszNodeName
) || (WspiapiParseV4Address(pszNodeName
, &dwAddress
))) {
330 if (!pszNodeName
) dwAddress
= htonl((iFlags
& AI_PASSIVE
) ? INADDR_ANY
: INADDR_LOOPBACK
);
331 *pptResult
= WspiapiNewAddrInfo(iSocketType
, iProtocol
, wPort
, dwAddress
);
332 if (!(*pptResult
)) iError
= EAI_MEMORY
;
333 if (!iError
&& pszNodeName
) {
334 (*pptResult
)->ai_flags
|= AI_NUMERICHOST
;
335 if (iFlags
& AI_CANONNAME
) {
336 (*pptResult
)->ai_canonname
= WspiapiStrdup(inet_ntoa(*((struct in_addr
*) &dwAddress
)));
337 if (!(*pptResult
)->ai_canonname
) iError
= EAI_MEMORY
;
341 else if (iFlags
& AI_NUMERICHOST
) {
345 iError
= WspiapiLookupNode(pszNodeName
, iSocketType
,
347 (iFlags
& AI_CANONNAME
),
350 if (!iError
&& bClone
) {
351 iError
= WspiapiClone(wUdpPort
, *pptResult
);
354 WspiapiLegacyFreeAddrInfo(*pptResult
);
364 WspiapiLegacyGetNameInfo(
365 IN
const struct sockaddr
*ptSocketAddress
,
366 IN socklen_t tSocketLength
,
367 OUT
char *pszNodeName
,
368 IN
size_t tNodeLength
,
369 OUT
char *pszServiceName
,
370 IN
size_t tServiceLength
,
373 struct servent
*ptService
;
375 char szBuffer
[] = "65535";
376 char *pszService
= szBuffer
;
377 struct hostent
*ptHost
;
378 struct in_addr tAddress
;
379 char *pszNode
= NULL
;
382 if ((!ptSocketAddress
) || (tSocketLength
< sizeof(struct sockaddr
))) return EAI_FAIL
;
383 if (ptSocketAddress
->sa_family
!= AF_INET
) return EAI_FAMILY
;
384 if (tSocketLength
< sizeof(struct sockaddr_in
)) return EAI_FAIL
;
385 if (!(pszNodeName
&& tNodeLength
) && !(pszServiceName
&& tServiceLength
)) {
388 if ((iFlags
& NI_NUMERICHOST
) && (iFlags
& NI_NAMEREQD
)) {
391 if (pszServiceName
&& tServiceLength
) {
392 wPort
= ((struct sockaddr_in
*) ptSocketAddress
)->sin_port
;
393 if (iFlags
& NI_NUMERICSERV
) {
394 _WSPIAPI_SPRINTF_S_1(szBuffer
, _WSPIAPI_COUNTOF(szBuffer
), "%u", ntohs(wPort
));
397 ptService
= getservbyport(wPort
, (iFlags
& NI_DGRAM
) ? "udp" : NULL
);
398 if (ptService
&& ptService
->s_name
) {
399 pszService
= ptService
->s_name
;
402 _WSPIAPI_SPRINTF_S_1(szBuffer
, _WSPIAPI_COUNTOF(szBuffer
), "%u", ntohs(wPort
));
405 if (tServiceLength
> strlen(pszService
))
406 _WSPIAPI_STRCPY_S(pszServiceName
, tServiceLength
, pszService
);
407 else return EAI_FAIL
;
409 if (pszNodeName
&& tNodeLength
) {
410 tAddress
= ((struct sockaddr_in
*) ptSocketAddress
)->sin_addr
;
411 if (iFlags
& NI_NUMERICHOST
) {
412 pszNode
= inet_ntoa(tAddress
);
415 ptHost
= gethostbyaddr((char *) &tAddress
, sizeof(struct in_addr
), AF_INET
);
416 if (ptHost
&& ptHost
->h_name
) {
417 pszNode
= ptHost
->h_name
;
418 if ((iFlags
& NI_NOFQDN
) && ((pc
= strchr(pszNode
, '.')) != NULL
)) *pc
= '\0';
421 if (iFlags
& NI_NAMEREQD
) {
422 switch (WSAGetLastError()) {
423 case WSAHOST_NOT_FOUND
: return EAI_NONAME
;
424 case WSATRY_AGAIN
: return EAI_AGAIN
;
425 case WSANO_RECOVERY
: return EAI_FAIL
;
426 default: return EAI_NONAME
;
429 else pszNode
= inet_ntoa(tAddress
);
432 if (tNodeLength
> strlen(pszNode
)) _WSPIAPI_STRCPY_S(pszNodeName
, tNodeLength
, pszNode
);
433 else return EAI_FAIL
;
444 #define WSPIAPI_FUNCTION_ARRAY { \
445 {"getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo}, \
446 {"getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo}, \
447 {"freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo} \
456 HMODULE hLibrary
= NULL
;
458 static BOOL bInitialized
= FALSE
;
459 static WSPIAPI_FUNCTION rgtGlobal
[] = WSPIAPI_FUNCTION_ARRAY
;
460 static const int iNumGlobal
= (sizeof(rgtGlobal
) / sizeof(WSPIAPI_FUNCTION
));
461 WSPIAPI_FUNCTION rgtLocal
[] = WSPIAPI_FUNCTION_ARRAY
;
462 FARPROC fScratch
= NULL
;
465 if (bInitialized
) return (rgtGlobal
[wFunction
].pfAddress
);
467 CHAR SystemDir
[MAX_PATH
+ 1];
468 CHAR Path
[MAX_PATH
+ 8];
469 if (GetSystemDirectoryA(SystemDir
, MAX_PATH
) == 0) break;
470 _WSPIAPI_STRCPY_S(Path
, _WSPIAPI_COUNTOF(Path
), SystemDir
);
471 _WSPIAPI_STRCAT_S(Path
, _WSPIAPI_COUNTOF(Path
), "\\ws2_32");
472 hLibrary
= LoadLibraryA(Path
);
473 if (hLibrary
!= NULL
) {
474 fScratch
= GetProcAddress(hLibrary
, "getaddrinfo");
475 if (fScratch
== NULL
) {
476 FreeLibrary(hLibrary
);
480 if (hLibrary
!= NULL
) break;
481 _WSPIAPI_STRCPY_S(Path
, _WSPIAPI_COUNTOF(Path
), SystemDir
);
482 _WSPIAPI_STRCAT_S(Path
, _WSPIAPI_COUNTOF(Path
), "\\wship6");
483 hLibrary
= LoadLibraryA(Path
);
484 if (hLibrary
!= NULL
) {
485 fScratch
= GetProcAddress(hLibrary
, "getaddrinfo");
486 if (fScratch
== NULL
) {
487 FreeLibrary(hLibrary
);
493 if (hLibrary
!= NULL
) {
494 for (i
= 0; i
< iNumGlobal
; i
++) {
495 rgtLocal
[i
].pfAddress
= GetProcAddress(hLibrary
, rgtLocal
[i
].pszName
);
496 if (rgtLocal
[i
].pfAddress
== NULL
) {
497 FreeLibrary(hLibrary
);
502 if (hLibrary
!= NULL
) {
503 for (i
= 0; i
< iNumGlobal
; i
++)
504 rgtGlobal
[i
].pfAddress
= rgtLocal
[i
].pfAddress
;
509 return (rgtGlobal
[wFunction
].pfAddress
);
516 IN
const char *nodename OPTIONAL
,
517 IN
const char *servname OPTIONAL
,
518 IN
const struct addrinfo
*hints OPTIONAL
,
519 OUT
struct addrinfo
**res
)
522 static WSPIAPI_PGETADDRINFO pfGetAddrInfo
= NULL
;
524 if (!pfGetAddrInfo
) pfGetAddrInfo
= (WSPIAPI_PGETADDRINFO
) WspiapiLoad(0);
525 iError
= (*pfGetAddrInfo
)(nodename
, servname
, hints
, res
);
526 WSASetLastError(iError
);
535 IN
const struct sockaddr
*sa
,
544 static WSPIAPI_PGETNAMEINFO pfGetNameInfo
= NULL
;
546 if (!pfGetNameInfo
) pfGetNameInfo
= (WSPIAPI_PGETNAMEINFO
) WspiapiLoad(1);
547 iError
= (*pfGetNameInfo
)(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
548 WSASetLastError(iError
);
557 IN
struct addrinfo
*ai
)
559 static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo
= NULL
;
561 if (!pfFreeAddrInfo
) pfFreeAddrInfo
= (WSPIAPI_PFREEADDRINFO
) WspiapiLoad(2);
562 (*pfFreeAddrInfo
)(ai
);
565 #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */