1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32/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
connect(IN SOCKET s,IN CONST struct sockaddr * name,IN INT namelen)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
listen(IN SOCKET s,IN INT backlog)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
getpeername(IN SOCKET s,OUT LPSOCKADDR name,IN OUT INT FAR * namelen)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
getsockname(IN SOCKET s,OUT LPSOCKADDR name,IN OUT INT FAR * namelen)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
getsockopt(IN SOCKET s,IN INT level,IN INT optname,OUT CHAR FAR * optval,IN OUT INT FAR * optlen)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
setsockopt(IN SOCKET s,IN INT level,IN INT optname,IN CONST CHAR FAR * optval,IN INT optlen)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
shutdown(IN SOCKET s,IN INT how)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
WSAConnect(IN SOCKET s,IN CONST struct sockaddr * name,IN INT namelen,IN LPWSABUF lpCallerData,OUT LPWSABUF lpCalleeData,IN LPQOS lpSQOS,IN LPQOS lpGQOS)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
WSAGetOverlappedResult(IN SOCKET s,IN LPWSAOVERLAPPED lpOverlapped,OUT LPDWORD lpcbTransfer,IN BOOL fWait,OUT LPDWORD lpdwFlags)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 }
644