Create a branch for cmake bringup.
[reactos.git] / 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 typedef int
49 (WINAPI *WSPIAPI_PGETADDRINFO)(
50 IN const char *nodename,
51 IN const char *servname,
52 IN const struct addrinfo *hints,
53 OUT struct addrinfo **res);
54
55 typedef int
56 (WINAPI *WSPIAPI_PGETNAMEINFO)(
57 IN const struct sockaddr *sa,
58 IN socklen_t salen,
59 OUT char *host,
60 IN size_t hostlen,
61 OUT char *serv,
62 IN size_t servlen,
63 IN int flags);
64
65 typedef void
66 (WINAPI *WSPIAPI_PFREEADDRINFO)(
67 IN struct addrinfo *ai);
68
69 FORCEINLINE
70 char *
71 WINAPI
72 WspiapiStrdup(
73 IN const char *pszString)
74 {
75 char *pszMemory;
76 size_t cchMemory;
77
78 if (!pszString) return(NULL);
79 cchMemory = strlen(pszString) + 1;
80 pszMemory = (char *) WspiapiMalloc(cchMemory);
81 if (!pszMemory) return(NULL);
82 _WSPIAPI_STRCPY_S(pszMemory, cchMemory, pszString);
83 return pszMemory;
84 }
85
86 FORCEINLINE
87 BOOL
88 WINAPI
89 WspiapiParseV4Address(
90 IN const char *pszAddress,
91 OUT PDWORD pdwAddress)
92 {
93 DWORD dwAddress = 0;
94 const char *pcNext = NULL;
95 int iCount = 0;
96
97 for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
98 if (*pcNext == '.') iCount++;
99 if (iCount != 3) return FALSE;
100 dwAddress = inet_addr(pszAddress);
101 if (dwAddress == INADDR_NONE) return FALSE;
102 *pdwAddress = dwAddress;
103 return TRUE;
104 }
105
106 FORCEINLINE
107 struct addrinfo *
108 WINAPI
109 WspiapiNewAddrInfo(
110 IN int iSocketType,
111 IN int iProtocol,
112 IN WORD wPort,
113 IN DWORD dwAddress)
114 {
115 struct addrinfo *ptNew;
116 struct sockaddr_in *ptAddress;
117
118 ptNew = (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
119 if (!ptNew) return NULL;
120 ptAddress = (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
121 if (!ptAddress) {
122 WspiapiFree(ptNew);
123 return NULL;
124 }
125 ptAddress->sin_family = AF_INET;
126 ptAddress->sin_port = wPort;
127 ptAddress->sin_addr.s_addr = dwAddress;
128 ptNew->ai_family = PF_INET;
129 ptNew->ai_socktype = iSocketType;
130 ptNew->ai_protocol = iProtocol;
131 ptNew->ai_addrlen = sizeof(struct sockaddr_in);
132 ptNew->ai_addr = (struct sockaddr *) ptAddress;
133
134 return ptNew;
135 }
136
137 FORCEINLINE
138 int
139 WINAPI
140 WspiapiQueryDNS(
141 IN const char *pszNodeName,
142 IN int iSocketType,
143 IN int iProtocol,
144 IN WORD wPort,
145 OUT char pszAlias[NI_MAXHOST],
146 OUT struct addrinfo **pptResult)
147 {
148 struct addrinfo **pptNext = pptResult;
149 struct hostent *ptHost = NULL;
150 char **ppAddresses;
151
152 *pptNext = NULL;
153 pszAlias[0] = '\0';
154
155 ptHost = gethostbyname(pszNodeName);
156 if (ptHost) {
157 if ((ptHost->h_addrtype == AF_INET) && (ptHost->h_length == sizeof(struct in_addr))) {
158 for (ppAddresses = ptHost->h_addr_list; *ppAddresses != NULL; ppAddresses++) {
159 *pptNext = WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, ((struct in_addr *) *ppAddresses)->s_addr);
160 if (!*pptNext) return EAI_MEMORY;
161 pptNext = &((*pptNext)->ai_next);
162 }
163 }
164 _WSPIAPI_STRNCPY_S(pszAlias, NI_MAXHOST, ptHost->h_name, NI_MAXHOST - 1);
165 return 0;
166 }
167 switch (WSAGetLastError()) {
168 case WSAHOST_NOT_FOUND: return EAI_NONAME;
169 case WSATRY_AGAIN: return EAI_AGAIN;
170 case WSANO_RECOVERY: return EAI_FAIL;
171 case WSANO_DATA: return EAI_NODATA;
172 default: return EAI_NONAME;
173 }
174 }
175
176 FORCEINLINE
177 int
178 WINAPI
179 WspiapiLookupNode(
180 IN const char *pszNodeName,
181 IN int iSocketType,
182 IN int iProtocol,
183 IN WORD wPort,
184 IN BOOL bAI_CANONNAME,
185 OUT struct addrinfo **pptResult)
186 {
187 int iError = 0;
188 int iAliasCount = 0;
189 char szFQDN1[NI_MAXHOST] = "";
190 char szFQDN2[NI_MAXHOST] = "";
191 char *pszName = szFQDN1;
192 char *pszAlias = szFQDN2;
193 char *pszScratch = NULL;
194
195 _WSPIAPI_STRNCPY_S(pszName, NI_MAXHOST, pszNodeName, NI_MAXHOST - 1);
196 for (;;) {
197 iError = WspiapiQueryDNS(pszNodeName, iSocketType, iProtocol, wPort, pszAlias, pptResult);
198 if (iError) break;
199 if (*pptResult) break;
200 if ((!strlen(pszAlias)) || (!strcmp(pszName, pszAlias)) || (++iAliasCount == 16)) {
201 iError = EAI_FAIL;
202 break;
203 }
204 WspiapiSwap(pszName, pszAlias, pszScratch);
205 }
206 if (!iError && bAI_CANONNAME) {
207 (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
208 if (!(*pptResult)->ai_canonname) iError = EAI_MEMORY;
209 }
210
211 return iError;
212 }
213
214
215
216 FORCEINLINE
217 int
218 WINAPI
219 WspiapiClone(
220 IN WORD wPort,
221 IN struct addrinfo *ptResult)
222 {
223 struct addrinfo *ptNext = NULL;
224 struct addrinfo *ptNew = NULL;
225
226 for (ptNext = ptResult; ptNext != NULL; ) {
227 ptNew = WspiapiNewAddrInfo(SOCK_DGRAM, ptNext->ai_protocol, wPort,
228 ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
229 if (!ptNew) break;
230 ptNew->ai_next = ptNext->ai_next;
231 ptNext->ai_next = ptNew;
232 ptNext = ptNew->ai_next;
233 }
234 if (ptNext != NULL) return EAI_MEMORY;
235
236 return 0;
237 }
238
239 FORCEINLINE
240 void
241 WINAPI
242 WspiapiLegacyFreeAddrInfo(
243 IN struct addrinfo *ptHead)
244 {
245 struct addrinfo *ptNext;
246
247 for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead) {
248 if (ptNext->ai_canonname) WspiapiFree(ptNext->ai_canonname);
249 if (ptNext->ai_addr) WspiapiFree(ptNext->ai_addr);
250 ptHead = ptNext->ai_next;
251 WspiapiFree(ptNext);
252 }
253 }
254
255 FORCEINLINE
256 int
257 WINAPI
258 WspiapiLegacyGetAddrInfo(
259 IN const char *pszNodeName,
260 IN const char *pszServiceName,
261 IN const struct addrinfo *ptHints,
262 OUT struct addrinfo **pptResult)
263 {
264 int iError = 0;
265 int iFlags = 0;
266 int iFamily = PF_UNSPEC;
267 int iSocketType = 0;
268 int iProtocol = 0;
269 WORD wPort = 0;
270 DWORD dwAddress = 0;
271 struct servent *ptService = NULL;
272 char *pc = NULL;
273 BOOL bClone = FALSE;
274 WORD wTcpPort = 0;
275 WORD wUdpPort = 0;
276 *pptResult = NULL;
277
278 if ((!pszNodeName) && (!pszServiceName)) return EAI_NONAME;
279 if (ptHints) {
280 if ((ptHints->ai_addrlen != 0) ||
281 (ptHints->ai_canonname != NULL) ||
282 (ptHints->ai_addr != NULL) ||
283 (ptHints->ai_next != NULL)) {
284 return EAI_FAIL;
285 }
286 iFlags = ptHints->ai_flags;
287 if ((iFlags & AI_CANONNAME) && !pszNodeName) return EAI_BADFLAGS;
288 iFamily = ptHints->ai_family;
289 if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET)) return EAI_FAMILY;
290 iSocketType = ptHints->ai_socktype;
291 if ((iSocketType != 0) &&
292 (iSocketType != SOCK_STREAM) &&
293 (iSocketType != SOCK_DGRAM) &&
294 (iSocketType != SOCK_RAW))
295 return EAI_SOCKTYPE;
296 iProtocol = ptHints->ai_protocol;
297 }
298 if (pszServiceName) {
299 wPort = (WORD) strtoul(pszServiceName, &pc, 10);
300 if (*pc == '\0') {
301 wPort = wTcpPort = wUdpPort = htons(wPort);
302 if (iSocketType == 0) {
303 bClone = TRUE;
304 iSocketType = SOCK_STREAM;
305 }
306 }
307 else {
308 if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM)) {
309 ptService = getservbyname(pszServiceName, "udp");
310 if (ptService) wPort = wUdpPort = ptService->s_port;
311 }
312 if ((iSocketType == 0) || (iSocketType == SOCK_STREAM)) {
313 ptService = getservbyname(pszServiceName, "tcp");
314 if (ptService) wPort = wTcpPort = ptService->s_port;
315 }
316 if (wPort == 0) return (iSocketType ? EAI_SERVICE : EAI_NONAME);
317 if (iSocketType == 0) {
318 iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
319 bClone = (wTcpPort && wUdpPort);
320 }
321 }
322 }
323 if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress))) {
324 if (!pszNodeName) dwAddress = htonl((iFlags & AI_PASSIVE) ? INADDR_ANY : INADDR_LOOPBACK);
325 *pptResult = WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
326 if (!(*pptResult)) iError = EAI_MEMORY;
327 if (!iError && pszNodeName) {
328 (*pptResult)->ai_flags |= AI_NUMERICHOST;
329 if (iFlags & AI_CANONNAME) {
330 (*pptResult)->ai_canonname = WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
331 if (!(*pptResult)->ai_canonname) iError = EAI_MEMORY;
332 }
333 }
334 }
335 else if (iFlags & AI_NUMERICHOST) {
336 iError = EAI_NONAME;
337 }
338 else {
339 iError = WspiapiLookupNode(pszNodeName, iSocketType,
340 iProtocol, wPort,
341 (iFlags & AI_CANONNAME),
342 pptResult);
343 }
344 if (!iError && bClone) {
345 iError = WspiapiClone(wUdpPort, *pptResult);
346 }
347 if (iError) {
348 WspiapiLegacyFreeAddrInfo(*pptResult);
349 *pptResult = NULL;
350 }
351
352 return (iError);
353 }
354
355 FORCEINLINE
356 int
357 WINAPI
358 WspiapiLegacyGetNameInfo(
359 IN const struct sockaddr *ptSocketAddress,
360 IN socklen_t tSocketLength,
361 OUT char *pszNodeName,
362 IN size_t tNodeLength,
363 OUT char *pszServiceName,
364 IN size_t tServiceLength,
365 IN int iFlags)
366 {
367 struct servent *ptService;
368 WORD wPort;
369 char szBuffer[] = "65535";
370 char *pszService = szBuffer;
371 struct hostent *ptHost;
372 struct in_addr tAddress;
373 char *pszNode = NULL;
374 char *pc = NULL;
375
376 if ((!ptSocketAddress) || (tSocketLength < sizeof(struct sockaddr))) return EAI_FAIL;
377 if (ptSocketAddress->sa_family != AF_INET) return EAI_FAMILY;
378 if (tSocketLength < sizeof(struct sockaddr_in)) return EAI_FAIL;
379 if (!(pszNodeName && tNodeLength) && !(pszServiceName && tServiceLength)) {
380 return EAI_NONAME;
381 }
382 if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD)) {
383 return EAI_BADFLAGS;
384 }
385 if (pszServiceName && tServiceLength) {
386 wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
387 if (iFlags & NI_NUMERICSERV) {
388 _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
389 }
390 else {
391 ptService = getservbyport(wPort, (iFlags & NI_DGRAM) ? "udp" : NULL);
392 if (ptService && ptService->s_name) {
393 pszService = ptService->s_name;
394 }
395 else {
396 _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
397 }
398 }
399 if (tServiceLength > strlen(pszService))
400 _WSPIAPI_STRCPY_S(pszServiceName, tServiceLength, pszService);
401 else return EAI_FAIL;
402 }
403 if (pszNodeName && tNodeLength) {
404 tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
405 if (iFlags & NI_NUMERICHOST) {
406 pszNode = inet_ntoa(tAddress);
407 }
408 else {
409 ptHost = gethostbyaddr((char *) &tAddress, sizeof(struct in_addr), AF_INET);
410 if (ptHost && ptHost->h_name) {
411 pszNode = ptHost->h_name;
412 if ((iFlags & NI_NOFQDN) && ((pc = strchr(pszNode, '.')) != NULL)) *pc = '\0';
413 }
414 else {
415 if (iFlags & NI_NAMEREQD) {
416 switch (WSAGetLastError()) {
417 case WSAHOST_NOT_FOUND: return EAI_NONAME;
418 case WSATRY_AGAIN: return EAI_AGAIN;
419 case WSANO_RECOVERY: return EAI_FAIL;
420 default: return EAI_NONAME;
421 }
422 }
423 else pszNode = inet_ntoa(tAddress);
424 }
425 }
426 if (tNodeLength > strlen(pszNode)) _WSPIAPI_STRCPY_S(pszNodeName, tNodeLength, pszNode);
427 else return EAI_FAIL;
428 }
429
430 return 0;
431 }
432
433 typedef struct {
434 char const *pszName;
435 FARPROC pfAddress;
436 } WSPIAPI_FUNCTION;
437
438 #define WSPIAPI_FUNCTION_ARRAY { \
439 "getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo, \
440 "getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo, \
441 "freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo, \
442 }
443
444 FORCEINLINE
445 FARPROC
446 WINAPI
447 WspiapiLoad(
448 IN WORD wFunction)
449 {
450 HMODULE hLibrary = NULL;
451
452 static BOOL bInitialized = FALSE;
453 static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
454 static const int iNumGlobal = (sizeof(rgtGlobal) / sizeof(WSPIAPI_FUNCTION));
455 WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
456 FARPROC fScratch = NULL;
457 int i = 0;
458
459 if (bInitialized) return (rgtGlobal[wFunction].pfAddress);
460 for (;;) {
461 CHAR SystemDir[MAX_PATH + 1];
462 CHAR Path[MAX_PATH + 8];
463 if (GetSystemDirectoryA(SystemDir, MAX_PATH) == 0) break;
464 _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
465 _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\ws2_32");
466 hLibrary = LoadLibraryA(Path);
467 if (hLibrary != NULL) {
468 fScratch = GetProcAddress(hLibrary, "getaddrinfo");
469 if (fScratch == NULL) {
470 FreeLibrary(hLibrary);
471 hLibrary = NULL;
472 }
473 }
474 if (hLibrary != NULL) break;
475 _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
476 _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\wship6");
477 hLibrary = LoadLibraryA(Path);
478 if (hLibrary != NULL) {
479 fScratch = GetProcAddress(hLibrary, "getaddrinfo");
480 if (fScratch == NULL) {
481 FreeLibrary(hLibrary);
482 hLibrary = NULL;
483 }
484 }
485 break;
486 }
487 if (hLibrary != NULL) {
488 for (i = 0; i < iNumGlobal; i++) {
489 rgtLocal[i].pfAddress = GetProcAddress(hLibrary, rgtLocal[i].pszName);
490 if (rgtLocal[i].pfAddress == NULL) {
491 FreeLibrary(hLibrary);
492 hLibrary = NULL;
493 break;
494 }
495 }
496 if (hLibrary != NULL) {
497 for (i = 0; i < iNumGlobal; i++)
498 rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
499 }
500 }
501 bInitialized = TRUE;
502
503 return (rgtGlobal[wFunction].pfAddress);
504 }
505
506 FORCEINLINE
507 int
508 WINAPI
509 WspiapiGetAddrInfo(
510 IN const char *nodename OPTIONAL,
511 IN const char *servname OPTIONAL,
512 IN const struct addrinfo *hints OPTIONAL,
513 OUT struct addrinfo **res)
514 {
515 int iError;
516 static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
517
518 if (!pfGetAddrInfo) pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
519 iError = (*pfGetAddrInfo)(nodename, servname, hints, res);
520 WSASetLastError(iError);
521
522 return iError;
523 }
524
525 FORCEINLINE
526 int
527 WINAPI
528 WspiapiGetNameInfo(
529 IN const struct sockaddr *sa,
530 IN socklen_t salen,
531 OUT char *host,
532 IN size_t hostlen,
533 OUT char *serv,
534 IN size_t servlen,
535 IN int flags)
536 {
537 int iError;
538 static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
539
540 if (!pfGetNameInfo) pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
541 iError = (*pfGetNameInfo)(sa, salen, host, hostlen, serv, servlen, flags);
542 WSASetLastError(iError);
543
544 return iError;
545 }
546
547 FORCEINLINE
548 void
549 WINAPI
550 WspiapiFreeAddrInfo(
551 IN struct addrinfo *ai)
552 {
553 static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL;
554
555 if (!pfFreeAddrInfo) pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
556 (*pfFreeAddrInfo)(ai);
557 }
558
559 #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */
560
561 #ifdef __cplusplus
562 }
563 #endif