2414b032315c2b5dece32a0c75a848da3a9b4a32
[reactos.git] / reactos / dll / win32 / ws2_32 / src / sockctrl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32_new/src/sockctrl.c
5 * PURPOSE: Socket Control/State Support
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ws2_32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 /*
19 * @implemented
20 */
21 INT
22 WSAAPI
23 connect(IN SOCKET s,
24 IN CONST struct sockaddr *name,
25 IN INT namelen)
26 {
27 PWSPROCESS Process;
28 PWSTHREAD Thread;
29 PWSSOCKET Socket;
30 INT ErrorCode, OldErrorCode = ERROR_SUCCESS;
31 INT Status;
32 BOOLEAN TryAgain = TRUE;
33 DPRINT("connect: %lx, %p, %lx\n", s, name, namelen);
34
35 /* Enter prolog */
36 ErrorCode = WsApiProlog(&Process, &Thread);
37 if (ErrorCode == ERROR_SUCCESS)
38 {
39 /* Get the Socket Context */
40 if ((Socket = WsSockGetSocket(s)))
41 {
42 while (TRUE)
43 {
44 /* Make the call */
45 Status = Socket->Provider->Service.lpWSPConnect(s,
46 name,
47 namelen,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 &ErrorCode);
53
54 /* Check if error code was due to the host not being found */
55 if ((Status == SOCKET_ERROR) &&
56 ((ErrorCode == WSAEHOSTUNREACH) ||
57 (ErrorCode == WSAENETUNREACH)))
58 {
59 /* Check if we can try again */
60 if (TryAgain)
61 {
62 /* Save the old error code */
63 OldErrorCode = ErrorCode;
64
65 /* Make sure we don't retry 3 times */
66 TryAgain = FALSE;
67
68 /* Make the RAS Auto-dial attempt */
69 if (WSAttemptAutodialAddr(name, namelen)) continue;
70 }
71 else
72 {
73 /* Restore the error code */
74 ErrorCode = OldErrorCode;
75 }
76 }
77
78 /* Break out of the loop */
79 break;
80 }
81
82 /* Deference the Socket Context */
83 WsSockDereference(Socket);
84
85 /* Return Provider Value */
86 if (Status == ERROR_SUCCESS) return Status;
87
88 /* If everything seemed fine, then the WSP call failed itself */
89 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
90 }
91 else
92 {
93 /* No Socket Context Found */
94 ErrorCode = WSAENOTSOCK;
95 }
96 }
97
98 /* If this is Winsock 1.1, normalize the error code */
99 if ((ErrorCode == WSAEALREADY) && (LOBYTE(Process->Version) == 1))
100 {
101 /* WS 1.1 apps expect this */
102 ErrorCode = WSAEINVAL;
103 }
104
105 /* Return with an Error */
106 SetLastError(ErrorCode);
107 return SOCKET_ERROR;
108 }
109
110 /*
111 * @implemented
112 */
113 INT
114 WSAAPI
115 listen(IN SOCKET s,
116 IN INT backlog)
117 {
118 PWSSOCKET Socket;
119 INT Status;
120 INT ErrorCode;
121 DPRINT("connect: %lx, %lx\n", s, backlog);
122
123 /* Check for WSAStartup */
124 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
125 {
126 /* Get the Socket Context */
127 if ((Socket = WsSockGetSocket(s)))
128 {
129 /* Make the call */
130 Status = Socket->Provider->Service.lpWSPListen(s,
131 backlog,
132 &ErrorCode);
133 /* Deference the Socket Context */
134 WsSockDereference(Socket);
135
136 /* Return Provider Value */
137 if (Status == ERROR_SUCCESS) return Status;
138
139 /* If everything seemed fine, then the WSP call failed itself */
140 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
141 }
142 else
143 {
144 /* No Socket Context Found */
145 ErrorCode = WSAENOTSOCK;
146 }
147 }
148
149 /* Return with an Error */
150 SetLastError(ErrorCode);
151 return SOCKET_ERROR;
152 }
153
154 /*
155 * @implemented
156 */
157 INT
158 WSAAPI
159 getpeername(IN SOCKET s,
160 OUT LPSOCKADDR name,
161 IN OUT INT FAR* namelen)
162 {
163 PWSSOCKET Socket;
164 INT Status;
165 INT ErrorCode;
166 DPRINT("getpeername: %lx, %p, %lx\n", s, name, namelen);
167
168 /* Check for WSAStartup */
169 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
170 {
171 /* Get the Socket Context */
172 if ((Socket = WsSockGetSocket(s)))
173 {
174 /* Make the call */
175 Status = Socket->Provider->Service.lpWSPGetPeerName(s,
176 name,
177 namelen,
178 &ErrorCode);
179 /* Deference the Socket Context */
180 WsSockDereference(Socket);
181
182 /* Return Provider Value */
183 if (Status == ERROR_SUCCESS) return Status;
184
185 /* If everything seemed fine, then the WSP call failed itself */
186 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
187 }
188 else
189 {
190 /* No Socket Context Found */
191 ErrorCode = WSAENOTSOCK;
192 }
193 }
194
195 /* Return with an Error */
196 SetLastError(ErrorCode);
197 return SOCKET_ERROR;
198 }
199
200 /*
201 * @implemented
202 */
203 INT
204 WSAAPI
205 getsockname(IN SOCKET s,
206 OUT LPSOCKADDR name,
207 IN OUT INT FAR* namelen)
208 {
209 PWSSOCKET Socket;
210 INT Status;
211 INT ErrorCode;
212 DPRINT("getsockname: %lx, %p, %lx\n", s, name, namelen);
213
214 /* Check for WSAStartup */
215 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
216 {
217 /* Get the Socket Context */
218 if ((Socket = WsSockGetSocket(s)))
219 {
220 if (name && namelen && (*namelen >= sizeof(*name)))
221 {
222 /* Make the call */
223 Status = Socket->Provider->Service.lpWSPGetSockName(s,
224 name,
225 namelen,
226 &ErrorCode);
227
228 /* Deference the Socket Context */
229 WsSockDereference(Socket);
230
231 /* Return Provider Value */
232 if (Status == ERROR_SUCCESS) return Status;
233
234 /* If everything seemed fine, then the WSP call failed itself */
235 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
236 }
237 else
238 {
239 /* Deference the Socket Context */
240 WsSockDereference(Socket);
241
242 /* name or namelen not valid */
243 ErrorCode = WSAEFAULT;
244 }
245 }
246 else
247 {
248 /* No Socket Context Found */
249 ErrorCode = WSAENOTSOCK;
250 }
251 }
252
253 /* Return with an Error */
254 SetLastError(ErrorCode);
255 return SOCKET_ERROR;
256 }
257
258 /*
259 * @implemented
260 */
261 INT
262 WSAAPI
263 getsockopt(IN SOCKET s,
264 IN INT level,
265 IN INT optname,
266 OUT CHAR FAR* optval,
267 IN OUT INT FAR* optlen)
268 {
269 PWSPROCESS Process;
270 PWSTHREAD Thread;
271 PWSSOCKET Socket;
272 INT ErrorCode;
273 INT Status;
274 WSAPROTOCOL_INFOW ProtocolInfo;
275 PCHAR OldOptVal = NULL;
276 INT OldOptLen = 0;
277 DPRINT("getsockopt: %lx, %lx, %lx\n", s, level, optname);
278
279 /* Enter prolog */
280 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
281 {
282 /* Check if we're getting the open type */
283 if ((level == SOL_SOCKET) && (optname == SO_OPENTYPE))
284 {
285 /* Validate size */
286 Status = ERROR_SUCCESS;
287 _SEH2_TRY
288 {
289 if (!(optlen) || (*optlen < sizeof(DWORD)))
290 {
291 /* Fail */
292 Status = SOCKET_ERROR;
293 SetLastError(WSAEFAULT);
294 _SEH2_LEAVE;
295 }
296
297 /* Set the open type */
298 *(DWORD*)optval = Thread->OpenType;
299 *optlen = sizeof(DWORD);
300 }
301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
302 {
303 Status = SOCKET_ERROR;
304 SetLastError(WSAEFAULT);
305 }
306 _SEH2_END;
307
308 return Status;
309 }
310
311 /* Get the Socket Context */
312 if ((Socket = WsSockGetSocket(s)))
313 {
314 /* Check if ANSI data was requested */
315 if ((level == SOL_SOCKET) && (optname == SO_PROTOCOL_INFOA))
316 {
317 /* Validate size and pointers */
318 ErrorCode = NO_ERROR;
319 _SEH2_TRY
320 {
321 if (!(optval) ||
322 !(optlen) ||
323 (*optlen < sizeof(WSAPROTOCOL_INFOA)))
324 {
325 /* Set return size and error code */
326 *optlen = sizeof(WSAPROTOCOL_INFOA);
327 ErrorCode = WSAEFAULT;
328 _SEH2_LEAVE;
329 }
330
331 /* It worked. Save the values */
332 OldOptLen = *optlen;
333 OldOptVal = optval;
334
335 /* Hack them so WSP will know how to deal with it */
336 *optlen = sizeof(WSAPROTOCOL_INFOW);
337 optval = (PCHAR)&ProtocolInfo;
338 optname = SO_PROTOCOL_INFOW;
339 }
340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
341 {
342 ErrorCode = WSAEFAULT;
343 }
344 _SEH2_END;
345
346 /* Did we encounter invalid parameters? */
347 if (ErrorCode != NO_ERROR)
348 {
349 /* Dereference the socket and fail */
350 WsSockDereference(Socket);
351 SetLastError(ErrorCode);
352 return SOCKET_ERROR;
353 }
354 }
355
356 /* Make the call */
357 Status = Socket->Provider->Service.lpWSPGetSockOpt(s,
358 level,
359 optname,
360 optval,
361 optlen,
362 &ErrorCode);
363
364 /* Deference the Socket Context */
365 WsSockDereference(Socket);
366
367 /* Check provider value */
368 if (Status == ERROR_SUCCESS)
369 {
370 /* Did we use the A->W hack? */
371 if (!OldOptVal) return Status;
372
373 /* We did, so we have to convert the unicode info to ansi */
374 ErrorCode = MapUnicodeProtocolInfoToAnsi(&ProtocolInfo,
375 (LPWSAPROTOCOL_INFOA)
376 OldOptVal);
377
378 /* Return the length */
379 _SEH2_TRY
380 {
381 *optlen = OldOptLen;
382 }
383 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
384 {
385 ErrorCode = WSAEFAULT;
386 }
387 _SEH2_END;
388
389 /* Return success if this worked */
390 if (ErrorCode == ERROR_SUCCESS) return Status;
391 }
392
393 /* If everything seemed fine, then the WSP call failed itself */
394 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
395 }
396 else
397 {
398 /* No Socket Context Found */
399 ErrorCode = WSAENOTSOCK;
400 }
401 }
402
403 /* Return with an Error */
404 SetLastError(ErrorCode);
405 return SOCKET_ERROR;
406 }
407
408 /*
409 * @implemented
410 */
411 INT
412 WSAAPI
413 setsockopt(IN SOCKET s,
414 IN INT level,
415 IN INT optname,
416 IN CONST CHAR FAR* optval,
417 IN INT optlen)
418 {
419 PWSPROCESS Process;
420 PWSTHREAD Thread;
421 PWSSOCKET Socket;
422 INT ErrorCode;
423 INT Status;
424 DPRINT("setsockopt: %lx, %lx, %lx\n", s, level, optname);
425
426 /* Enter prolog */
427 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
428 {
429 /* Check if we're changing the open type */
430 if (level == SOL_SOCKET && optname == SO_OPENTYPE)
431 {
432 /* Validate size */
433 if (optlen < sizeof(DWORD))
434 {
435 /* Fail */
436 SetLastError(WSAEFAULT);
437 return SOCKET_ERROR;
438 }
439
440 /* Set the open type */
441 Status = ERROR_SUCCESS;
442 _SEH2_TRY
443 {
444 Thread->OpenType = *(DWORD*)optval;
445 }
446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
447 {
448 Status = SOCKET_ERROR;
449 SetLastError(WSAEFAULT);
450 }
451 _SEH2_END;
452
453 return Status;
454 }
455 if (!optval && optlen > 0)
456 {
457 SetLastError(WSAEFAULT);
458 return SOCKET_ERROR;
459 }
460
461 /* Get the Socket Context */
462 if ((Socket = WsSockGetSocket(s)))
463 {
464 /* Make the call */
465 Status = Socket->Provider->Service.lpWSPSetSockOpt(s,
466 level,
467 optname,
468 optval,
469 optlen,
470 &ErrorCode);
471
472 /* Deference the Socket Context */
473 WsSockDereference(Socket);
474
475 /* Return Provider Value */
476 if (Status == ERROR_SUCCESS) return Status;
477
478 /* If everything seemed fine, then the WSP call failed itself */
479 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
480 }
481 else
482 {
483 /* No Socket Context Found */
484 ErrorCode = WSAENOTSOCK;
485 }
486 }
487
488 /* Return with an Error */
489 SetLastError(ErrorCode);
490 return SOCKET_ERROR;
491 }
492
493 /*
494 * @implemented
495 */
496 INT
497 WSAAPI
498 shutdown(IN SOCKET s,
499 IN INT how)
500 {
501 PWSSOCKET Socket;
502 INT Status;
503 INT ErrorCode;
504 DPRINT("shutdown: %lx, %lx\n", s, how);
505
506 /* Check for WSAStartup */
507 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
508 {
509 /* Get the Socket Context */
510 if ((Socket = WsSockGetSocket(s)))
511 {
512 /* Make the call */
513 Status = Socket->Provider->Service.lpWSPShutdown(s, how, &ErrorCode);
514
515 /* Deference the Socket Context */
516 WsSockDereference(Socket);
517
518 /* Return Provider Value */
519 if (Status == ERROR_SUCCESS) return Status;
520
521 /* If everything seemed fine, then the WSP call failed itself */
522 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
523 }
524 else
525 {
526 /* No Socket Context Found */
527 ErrorCode = WSAENOTSOCK;
528 }
529 }
530
531 /* Return with an Error */
532 SetLastError(ErrorCode);
533 return SOCKET_ERROR;
534 }
535
536 /*
537 * @implemented
538 */
539 INT
540 WSAAPI
541 WSAConnect(IN SOCKET s,
542 IN CONST struct sockaddr *name,
543 IN INT namelen,
544 IN LPWSABUF lpCallerData,
545 OUT LPWSABUF lpCalleeData,
546 IN LPQOS lpSQOS,
547 IN LPQOS lpGQOS)
548 {
549 PWSSOCKET Socket;
550 INT Status;
551 INT ErrorCode;
552 DPRINT("WSAConnect: %lx, %lx, %lx, %p\n", s, name, namelen, lpCallerData);
553
554 /* Check for WSAStartup */
555 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
556 {
557 /* Get the Socket Context */
558 if ((Socket = WsSockGetSocket(s)))
559 {
560 /* Make the call */
561 Status = Socket->Provider->Service.lpWSPConnect(s,
562 name,
563 namelen,
564 lpCallerData,
565 lpCalleeData,
566 lpSQOS,
567 lpGQOS,
568 &ErrorCode);
569 /* Deference the Socket Context */
570 WsSockDereference(Socket);
571
572 /* Return Provider Value */
573 if (Status == ERROR_SUCCESS) return Status;
574
575 /* If everything seemed fine, then the WSP call failed itself */
576 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
577 }
578 else
579 {
580 /* No Socket Context Found */
581 ErrorCode = WSAENOTSOCK;
582 }
583 }
584
585 /* Return with an Error */
586 SetLastError(ErrorCode);
587 return SOCKET_ERROR;
588 }
589
590 /*
591 * @implemented
592 */
593 BOOL
594 WSAAPI
595 WSAGetOverlappedResult(IN SOCKET s,
596 IN LPWSAOVERLAPPED lpOverlapped,
597 OUT LPDWORD lpcbTransfer,
598 IN BOOL fWait,
599 OUT LPDWORD lpdwFlags)
600 {
601 PWSSOCKET Socket;
602 INT Status;
603 INT ErrorCode;
604 DPRINT("WSAGetOverlappedResult: %lx, %lx\n", s, lpOverlapped);
605
606 /* Check for WSAStartup */
607 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
608 {
609 /* Get the Socket Context */
610 if ((Socket = WsSockGetSocket(s)))
611 {
612 /* Make the call */
613 Status = Socket->Provider->Service.lpWSPGetOverlappedResult(s,
614 lpOverlapped,
615 lpcbTransfer,
616 fWait,
617 lpdwFlags,
618 &ErrorCode);
619 /* Deference the Socket Context */
620 WsSockDereference(Socket);
621
622 /* Return Provider Value */
623 if (Status) return Status;
624 }
625 else
626 {
627 /* No Socket Context Found */
628 ErrorCode = WSAENOTSOCK;
629 }
630 }
631
632 /* Return with an Error */
633 SetLastError(ErrorCode);
634 return FALSE;
635 }