[RXCE]
[reactos.git] / reactos / sdk / include / psdk / wspiapi.h
1 #pragma once
2
3 #ifdef __cplusplus
4 extern "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
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))
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
54 typedef 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
61 typedef 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
71 typedef void
72 (WINAPI *WSPIAPI_PFREEADDRINFO)(
73 IN struct addrinfo *ai);
74
75 FORCEINLINE
76 char *
77 WINAPI
78 WspiapiStrdup(
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
92 FORCEINLINE
93 BOOL
94 WINAPI
95 WspiapiParseV4Address(
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
112 FORCEINLINE
113 struct addrinfo *
114 WINAPI
115 WspiapiNewAddrInfo(
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
143 FORCEINLINE
144 int
145 WINAPI
146 WspiapiQueryDNS(
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
182 FORCEINLINE
183 int
184 WINAPI
185 WspiapiLookupNode(
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
222 FORCEINLINE
223 int
224 WINAPI
225 WspiapiClone(
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
245 static __inline
246 void
247 WINAPI
248 WspiapiLegacyFreeAddrInfo(
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
261 static __inline
262 int
263 WINAPI
264 WspiapiLegacyGetAddrInfo(
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
361 static __inline
362 int
363 WINAPI
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,
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
439 typedef 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
450 WSPIAPI_INLINE
451 FARPROC
452 WINAPI
453 WspiapiLoad(
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
512 WSPIAPI_INLINE
513 int
514 WINAPI
515 WspiapiGetAddrInfo(
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
531 WSPIAPI_INLINE
532 int
533 WINAPI
534 WspiapiGetNameInfo(
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
553 WSPIAPI_INLINE
554 void
555 WINAPI
556 WspiapiFreeAddrInfo(
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