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