Reactos
at master 569 lines 15 kB view raw
1#pragma once 2 3#ifdef __cplusplus 4extern "C" { 5#endif 6 7#if (NTDDI_VERSION >= NTDDI_WIN2K) 8 9#include <stdio.h> 10#include <stdlib.h> 11#include <malloc.h> 12#include <string.h> 13 14#if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L 15 16#define _WSPIAPI_STRCPY_S strcpy_s 17#define _WSPIAPI_STRCAT_S strcat_s 18 19#else 20 21#define _WSPIAPI_STRCPY_S(_Dst, _Size, _Src) strcpy((_Dst), (_Src)) 22#define _WSPIAPI_STRCAT_S(_Dst, _Size, _Src) strcat((_Dst), (_Src)) 23 24#endif /* defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L */ 25 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 28 29#if !defined(_WSPIAPI_COUNTOF) 30 31#if !defined(__cplusplus) 32#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) 33#else 34template <typename __CountofType, size_t _N> 35char (&__wspiapi_countof_helper(__CountofType (&_Array)[_N]))[_N]; 36#define _WSPIAPI_COUNTOF(_Array) sizeof(__wspiapi_countof_helper(_Array)) 37#endif 38 39#endif /* !defined(_WSPIAPI_COUNTOF) */ 40 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 47 48#if _MSC_VER 49#define WSPIAPI_INLINE __inline 50#else 51#define WSPIAPI_INLINE static inline 52#endif 53 54typedef int 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); 60 61typedef int 62(WINAPI *WSPIAPI_PGETNAMEINFO)( 63 IN const struct sockaddr *sa, 64 IN socklen_t salen, 65 OUT char *host, 66 IN size_t hostlen, 67 OUT char *serv, 68 IN size_t servlen, 69 IN int flags); 70 71typedef void 72(WINAPI *WSPIAPI_PFREEADDRINFO)( 73 IN struct addrinfo *ai); 74 75FORCEINLINE 76char * 77WINAPI 78WspiapiStrdup( 79 IN const char *pszString) 80{ 81 char *pszMemory; 82 size_t cchMemory; 83 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); 89 return pszMemory; 90} 91 92FORCEINLINE 93BOOL 94WINAPI 95WspiapiParseV4Address( 96 IN const char *pszAddress, 97 OUT PDWORD pdwAddress) 98{ 99 DWORD dwAddress = 0; 100 const char *pcNext = NULL; 101 int iCount = 0; 102 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; 109 return TRUE; 110} 111 112FORCEINLINE 113struct addrinfo * 114WINAPI 115WspiapiNewAddrInfo( 116 IN int iSocketType, 117 IN int iProtocol, 118 IN WORD wPort, 119 IN DWORD dwAddress) 120{ 121 struct addrinfo *ptNew; 122 struct sockaddr_in *ptAddress; 123 124 ptNew = (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo)); 125 if (!ptNew) return NULL; 126 ptAddress = (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in)); 127 if (!ptAddress) { 128 WspiapiFree(ptNew); 129 return NULL; 130 } 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; 139 140 return ptNew; 141} 142 143FORCEINLINE 144int 145WINAPI 146WspiapiQueryDNS( 147 IN const char *pszNodeName, 148 IN int iSocketType, 149 IN int iProtocol, 150 IN WORD wPort, 151 OUT char pszAlias[NI_MAXHOST], 152 OUT struct addrinfo **pptResult) 153{ 154 struct addrinfo **pptNext = pptResult; 155 struct hostent *ptHost = NULL; 156 char **ppAddresses; 157 158 *pptNext = NULL; 159 pszAlias[0] = '\0'; 160 161 ptHost = gethostbyname(pszNodeName); 162 if (ptHost) { 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); 168 } 169 } 170 _WSPIAPI_STRNCPY_S(pszAlias, NI_MAXHOST, ptHost->h_name, NI_MAXHOST - 1); 171 return 0; 172 } 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; 179 } 180} 181 182FORCEINLINE 183int 184WINAPI 185WspiapiLookupNode( 186 IN const char *pszNodeName, 187 IN int iSocketType, 188 IN int iProtocol, 189 IN WORD wPort, 190 IN BOOL bAI_CANONNAME, 191 OUT struct addrinfo **pptResult) 192{ 193 int iError = 0; 194 int iAliasCount = 0; 195 char szFQDN1[NI_MAXHOST] = ""; 196 char szFQDN2[NI_MAXHOST] = ""; 197 char *pszName = szFQDN1; 198 char *pszAlias = szFQDN2; 199 char *pszScratch = NULL; 200 201 _WSPIAPI_STRNCPY_S(pszName, NI_MAXHOST, pszNodeName, NI_MAXHOST - 1); 202 for (;;) { 203 iError = WspiapiQueryDNS(pszNodeName, iSocketType, iProtocol, wPort, pszAlias, pptResult); 204 if (iError) break; 205 if (*pptResult) break; 206 if ((!strlen(pszAlias)) || (!strcmp(pszName, pszAlias)) || (++iAliasCount == 16)) { 207 iError = EAI_FAIL; 208 break; 209 } 210 WspiapiSwap(pszName, pszAlias, pszScratch); 211 } 212 if (!iError && bAI_CANONNAME) { 213 (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias); 214 if (!(*pptResult)->ai_canonname) iError = EAI_MEMORY; 215 } 216 217 return iError; 218} 219 220 221 222FORCEINLINE 223int 224WINAPI 225WspiapiClone( 226 IN WORD wPort, 227 IN struct addrinfo *ptResult) 228{ 229 struct addrinfo *ptNext = NULL; 230 struct addrinfo *ptNew = NULL; 231 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); 235 if (!ptNew) break; 236 ptNew->ai_next = ptNext->ai_next; 237 ptNext->ai_next = ptNew; 238 ptNext = ptNew->ai_next; 239 } 240 if (ptNext != NULL) return EAI_MEMORY; 241 242 return 0; 243} 244 245static __inline 246void 247WINAPI 248WspiapiLegacyFreeAddrInfo( 249 IN struct addrinfo *ptHead) 250{ 251 struct addrinfo *ptNext; 252 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; 257 WspiapiFree(ptNext); 258 } 259} 260 261static __inline 262int 263WINAPI 264WspiapiLegacyGetAddrInfo( 265 IN const char *pszNodeName, 266 IN const char *pszServiceName, 267 IN const struct addrinfo *ptHints, 268 OUT struct addrinfo **pptResult) 269{ 270 int iError = 0; 271 int iFlags = 0; 272 int iFamily = PF_UNSPEC; 273 int iSocketType = 0; 274 int iProtocol = 0; 275 WORD wPort = 0; 276 DWORD dwAddress = 0; 277 struct servent *ptService = NULL; 278 char *pc = NULL; 279 BOOL bClone = FALSE; 280 WORD wTcpPort = 0; 281 WORD wUdpPort = 0; 282 *pptResult = NULL; 283 284 if ((!pszNodeName) && (!pszServiceName)) return EAI_NONAME; 285 if (ptHints) { 286 if ((ptHints->ai_addrlen != 0) || 287 (ptHints->ai_canonname != NULL) || 288 (ptHints->ai_addr != NULL) || 289 (ptHints->ai_next != NULL)) { 290 return EAI_FAIL; 291 } 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)) 301 return EAI_SOCKTYPE; 302 iProtocol = ptHints->ai_protocol; 303 } 304 if (pszServiceName) { 305 wPort = (WORD) strtoul(pszServiceName, &pc, 10); 306 if (*pc == '\0') { 307 wPort = wTcpPort = wUdpPort = htons(wPort); 308 if (iSocketType == 0) { 309 bClone = TRUE; 310 iSocketType = SOCK_STREAM; 311 } 312 } 313 else { 314 if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM)) { 315 ptService = getservbyname(pszServiceName, "udp"); 316 if (ptService) wPort = wUdpPort = ptService->s_port; 317 } 318 if ((iSocketType == 0) || (iSocketType == SOCK_STREAM)) { 319 ptService = getservbyname(pszServiceName, "tcp"); 320 if (ptService) wPort = wTcpPort = ptService->s_port; 321 } 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); 326 } 327 } 328 } 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; 338 } 339 } 340 } 341 else if (iFlags & AI_NUMERICHOST) { 342 iError = EAI_NONAME; 343 } 344 else { 345 iError = WspiapiLookupNode(pszNodeName, iSocketType, 346 iProtocol, wPort, 347 (iFlags & AI_CANONNAME), 348 pptResult); 349 } 350 if (!iError && bClone) { 351 iError = WspiapiClone(wUdpPort, *pptResult); 352 } 353 if (iError) { 354 WspiapiLegacyFreeAddrInfo(*pptResult); 355 *pptResult = NULL; 356 } 357 358 return (iError); 359} 360 361static __inline 362int 363WINAPI 364WspiapiLegacyGetNameInfo( 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, 371 IN int iFlags) 372{ 373 struct servent *ptService; 374 WORD wPort; 375 char szBuffer[] = "65535"; 376 char *pszService = szBuffer; 377 struct hostent *ptHost; 378 struct in_addr tAddress; 379 char *pszNode = NULL; 380 char *pc = NULL; 381 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)) { 386 return EAI_NONAME; 387 } 388 if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD)) { 389 return EAI_BADFLAGS; 390 } 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)); 395 } 396 else { 397 ptService = getservbyport(wPort, (iFlags & NI_DGRAM) ? "udp" : NULL); 398 if (ptService && ptService->s_name) { 399 pszService = ptService->s_name; 400 } 401 else { 402 _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort)); 403 } 404 } 405 if (tServiceLength > strlen(pszService)) 406 _WSPIAPI_STRCPY_S(pszServiceName, tServiceLength, pszService); 407 else return EAI_FAIL; 408 } 409 if (pszNodeName && tNodeLength) { 410 tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr; 411 if (iFlags & NI_NUMERICHOST) { 412 pszNode = inet_ntoa(tAddress); 413 } 414 else { 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'; 419 } 420 else { 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; 427 } 428 } 429 else pszNode = inet_ntoa(tAddress); 430 } 431 } 432 if (tNodeLength > strlen(pszNode)) _WSPIAPI_STRCPY_S(pszNodeName, tNodeLength, pszNode); 433 else return EAI_FAIL; 434 } 435 436 return 0; 437} 438 439typedef struct { 440 char const *pszName; 441 FARPROC pfAddress; 442} WSPIAPI_FUNCTION; 443 444#define WSPIAPI_FUNCTION_ARRAY { \ 445 {"getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo}, \ 446 {"getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo}, \ 447 {"freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo} \ 448} 449 450WSPIAPI_INLINE 451FARPROC 452WINAPI 453WspiapiLoad( 454 IN WORD wFunction) 455{ 456 HMODULE hLibrary = NULL; 457 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; 463 int i = 0; 464 465 if (bInitialized) return (rgtGlobal[wFunction].pfAddress); 466 for (;;) { 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); 477 hLibrary = NULL; 478 } 479 } 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); 488 hLibrary = NULL; 489 } 490 } 491 break; 492 } 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); 498 hLibrary = NULL; 499 break; 500 } 501 } 502 if (hLibrary != NULL) { 503 for (i = 0; i < iNumGlobal; i++) 504 rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress; 505 } 506 } 507 bInitialized = TRUE; 508 509 return (rgtGlobal[wFunction].pfAddress); 510} 511 512WSPIAPI_INLINE 513int 514WINAPI 515WspiapiGetAddrInfo( 516 IN const char *nodename OPTIONAL, 517 IN const char *servname OPTIONAL, 518 IN const struct addrinfo *hints OPTIONAL, 519 OUT struct addrinfo **res) 520{ 521 int iError; 522 static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL; 523 524 if (!pfGetAddrInfo) pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0); 525 iError = (*pfGetAddrInfo)(nodename, servname, hints, res); 526 WSASetLastError(iError); 527 528 return iError; 529} 530 531WSPIAPI_INLINE 532int 533WINAPI 534WspiapiGetNameInfo( 535 IN const struct sockaddr *sa, 536 IN socklen_t salen, 537 OUT char *host, 538 IN size_t hostlen, 539 OUT char *serv, 540 IN size_t servlen, 541 IN int flags) 542{ 543 int iError; 544 static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL; 545 546 if (!pfGetNameInfo) pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1); 547 iError = (*pfGetNameInfo)(sa, salen, host, hostlen, serv, servlen, flags); 548 WSASetLastError(iError); 549 550 return iError; 551} 552 553WSPIAPI_INLINE 554void 555WINAPI 556WspiapiFreeAddrInfo( 557 IN struct addrinfo *ai) 558{ 559 static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL; 560 561 if (!pfFreeAddrInfo) pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2); 562 (*pfFreeAddrInfo)(ai); 563} 564 565#endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ 566 567#ifdef __cplusplus 568} 569#endif