1bf9e821249e09dc0740222262b0484e68ca7dff
[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 /* name or namelen not valid */
240 ErrorCode = WSAEFAULT;
241 }
242 }
243 else
244 {
245 /* No Socket Context Found */
246 ErrorCode = WSAENOTSOCK;
247 }
248 }
249
250 /* Return with an Error */
251 SetLastError(ErrorCode);
252 return SOCKET_ERROR;
253 }
254
255 /*
256 * @implemented
257 */
258 INT
259 WSAAPI
260 getsockopt(IN SOCKET s,
261 IN INT level,
262 IN INT optname,
263 OUT CHAR FAR* optval,
264 IN OUT INT FAR* optlen)
265 {
266 PWSPROCESS Process;
267 PWSTHREAD Thread;
268 PWSSOCKET Socket;
269 INT ErrorCode;
270 INT Status;
271 WSAPROTOCOL_INFOW ProtocolInfo;
272 PCHAR OldOptVal = NULL;
273 INT OldOptLen = 0;
274 DPRINT("getsockopt: %lx, %lx, %lx\n", s, level, optname);
275
276 /* Enter prolog */
277 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
278 {
279 /* Check if we're getting the open type */
280 if ((level == SOL_SOCKET) && (optname == SO_OPENTYPE))
281 {
282 /* Validate size */
283 Status = ERROR_SUCCESS;
284 _SEH2_TRY
285 {
286 if (!(optlen) || (*optlen < sizeof(DWORD)))
287 {
288 /* Fail */
289 Status = SOCKET_ERROR;
290 SetLastError(WSAEFAULT);
291 _SEH2_LEAVE;
292 }
293
294 /* Set the open type */
295 *(DWORD*)optval = Thread->OpenType;
296 *optlen = sizeof(DWORD);
297 }
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
299 {
300 Status = SOCKET_ERROR;
301 SetLastError(WSAEFAULT);
302 }
303 _SEH2_END;
304
305 return Status;
306 }
307
308 /* Get the Socket Context */
309 if ((Socket = WsSockGetSocket(s)))
310 {
311 /* Check if ANSI data was requested */
312 if ((level == SOL_SOCKET) && (optname == SO_PROTOCOL_INFOA))
313 {
314 /* Validate size and pointers */
315 ErrorCode = NO_ERROR;
316 _SEH2_TRY
317 {
318 if (!(optval) ||
319 !(optlen) ||
320 (*optlen < sizeof(WSAPROTOCOL_INFOA)))
321 {
322 /* Set return size and error code */
323 *optlen = sizeof(WSAPROTOCOL_INFOA);
324 ErrorCode = WSAEFAULT;
325 _SEH2_LEAVE;
326 }
327
328 /* It worked. Save the values */
329 OldOptLen = *optlen;
330 OldOptVal = optval;
331
332 /* Hack them so WSP will know how to deal with it */
333 *optlen = sizeof(WSAPROTOCOL_INFOW);
334 optval = (PCHAR)&ProtocolInfo;
335 optname = SO_PROTOCOL_INFOW;
336 }
337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
338 {
339 ErrorCode = WSAEFAULT;
340 }
341 _SEH2_END;
342
343 /* Did we encounter invalid parameters? */
344 if (ErrorCode != NO_ERROR)
345 {
346 /* Dereference the socket and fail */
347 WsSockDereference(Socket);
348 SetLastError(ErrorCode);
349 return SOCKET_ERROR;
350 }
351 }
352
353 /* Make the call */
354 Status = Socket->Provider->Service.lpWSPGetSockOpt(s,
355 level,
356 optname,
357 optval,
358 optlen,
359 &ErrorCode);
360
361 /* Deference the Socket Context */
362 WsSockDereference(Socket);
363
364 /* Check provider value */
365 if (Status == ERROR_SUCCESS)
366 {
367 /* Did we use the A->W hack? */
368 if (!OldOptVal) return Status;
369
370 /* We did, so we have to convert the unicode info to ansi */
371 ErrorCode = MapUnicodeProtocolInfoToAnsi(&ProtocolInfo,
372 (LPWSAPROTOCOL_INFOA)
373 OldOptVal);
374
375 /* Return the length */
376 _SEH2_TRY
377 {
378 *optlen = OldOptLen;
379 }
380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
381 {
382 ErrorCode = WSAEFAULT;
383 }
384 _SEH2_END;
385
386 /* Return success if this worked */
387 if (ErrorCode == ERROR_SUCCESS) return Status;
388 }
389
390 /* If everything seemed fine, then the WSP call failed itself */
391 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
392 }
393 else
394 {
395 /* No Socket Context Found */
396 ErrorCode = WSAENOTSOCK;
397 }
398 }
399
400 /* Return with an Error */
401 SetLastError(ErrorCode);
402 return SOCKET_ERROR;
403 }
404
405 /*
406 * @implemented
407 */
408 INT
409 WSAAPI
410 setsockopt(IN SOCKET s,
411 IN INT level,
412 IN INT optname,
413 IN CONST CHAR FAR* optval,
414 IN INT optlen)
415 {
416 PWSPROCESS Process;
417 PWSTHREAD Thread;
418 PWSSOCKET Socket;
419 INT ErrorCode;
420 INT Status;
421 DPRINT("setsockopt: %lx, %lx, %lx\n", s, level, optname);
422
423 /* Enter prolog */
424 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
425 {
426 /* Check if we're changing the open type */
427 if (level == SOL_SOCKET && optname == SO_OPENTYPE)
428 {
429 /* Validate size */
430 if (optlen < sizeof(DWORD))
431 {
432 /* Fail */
433 SetLastError(WSAEFAULT);
434 return SOCKET_ERROR;
435 }
436
437 /* Set the open type */
438 Status = ERROR_SUCCESS;
439 _SEH2_TRY
440 {
441 Thread->OpenType = *(DWORD*)optval;
442 }
443 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
444 {
445 Status = SOCKET_ERROR;
446 SetLastError(WSAEFAULT);
447 }
448 _SEH2_END;
449
450 return Status;
451 }
452 if (!optval && optlen > 0)
453 {
454 SetLastError(WSAEFAULT);
455 return SOCKET_ERROR;
456 }
457
458 /* Get the Socket Context */
459 if ((Socket = WsSockGetSocket(s)))
460 {
461 /* Make the call */
462 Status = Socket->Provider->Service.lpWSPSetSockOpt(s,
463 level,
464 optname,
465 optval,
466 optlen,
467 &ErrorCode);
468
469 /* Deference the Socket Context */
470 WsSockDereference(Socket);
471
472 /* Return Provider Value */
473 if (Status == ERROR_SUCCESS) return Status;
474
475 /* If everything seemed fine, then the WSP call failed itself */
476 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
477 }
478 else
479 {
480 /* No Socket Context Found */
481 ErrorCode = WSAENOTSOCK;
482 }
483 }
484
485 /* Return with an Error */
486 SetLastError(ErrorCode);
487 return SOCKET_ERROR;
488 }
489
490 /*
491 * @implemented
492 */
493 INT
494 WSAAPI
495 shutdown(IN SOCKET s,
496 IN INT how)
497 {
498 PWSSOCKET Socket;
499 INT Status;
500 INT ErrorCode;
501 DPRINT("shutdown: %lx, %lx\n", s, how);
502
503 /* Check for WSAStartup */
504 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
505 {
506 /* Get the Socket Context */
507 if ((Socket = WsSockGetSocket(s)))
508 {
509 /* Make the call */
510 Status = Socket->Provider->Service.lpWSPShutdown(s, how, &ErrorCode);
511
512 /* Deference the Socket Context */
513 WsSockDereference(Socket);
514
515 /* Return Provider Value */
516 if (Status == ERROR_SUCCESS) return Status;
517
518 /* If everything seemed fine, then the WSP call failed itself */
519 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
520 }
521 else
522 {
523 /* No Socket Context Found */
524 ErrorCode = WSAENOTSOCK;
525 }
526 }
527
528 /* Return with an Error */
529 SetLastError(ErrorCode);
530 return SOCKET_ERROR;
531 }
532
533 /*
534 * @implemented
535 */
536 INT
537 WSAAPI
538 WSAConnect(IN SOCKET s,
539 IN CONST struct sockaddr *name,
540 IN INT namelen,
541 IN LPWSABUF lpCallerData,
542 OUT LPWSABUF lpCalleeData,
543 IN LPQOS lpSQOS,
544 IN LPQOS lpGQOS)
545 {
546 PWSSOCKET Socket;
547 INT Status;
548 INT ErrorCode;
549 DPRINT("WSAConnect: %lx, %lx, %lx, %p\n", s, name, namelen, lpCallerData);
550
551 /* Check for WSAStartup */
552 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
553 {
554 /* Get the Socket Context */
555 if ((Socket = WsSockGetSocket(s)))
556 {
557 /* Make the call */
558 Status = Socket->Provider->Service.lpWSPConnect(s,
559 name,
560 namelen,
561 lpCallerData,
562 lpCalleeData,
563 lpSQOS,
564 lpGQOS,
565 &ErrorCode);
566 /* Deference the Socket Context */
567 WsSockDereference(Socket);
568
569 /* Return Provider Value */
570 if (Status == ERROR_SUCCESS) return Status;
571
572 /* If everything seemed fine, then the WSP call failed itself */
573 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
574 }
575 else
576 {
577 /* No Socket Context Found */
578 ErrorCode = WSAENOTSOCK;
579 }
580 }
581
582 /* Return with an Error */
583 SetLastError(ErrorCode);
584 return SOCKET_ERROR;
585 }
586
587 /*
588 * @implemented
589 */
590 BOOL
591 WSAAPI
592 WSAGetOverlappedResult(IN SOCKET s,
593 IN LPWSAOVERLAPPED lpOverlapped,
594 OUT LPDWORD lpcbTransfer,
595 IN BOOL fWait,
596 OUT LPDWORD lpdwFlags)
597 {
598 PWSSOCKET Socket;
599 INT Status;
600 INT ErrorCode;
601 DPRINT("WSAGetOverlappedResult: %lx, %lx\n", s, lpOverlapped);
602
603 /* Check for WSAStartup */
604 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
605 {
606 /* Get the Socket Context */
607 if ((Socket = WsSockGetSocket(s)))
608 {
609 /* Make the call */
610 Status = Socket->Provider->Service.lpWSPGetOverlappedResult(s,
611 lpOverlapped,
612 lpcbTransfer,
613 fWait,
614 lpdwFlags,
615 &ErrorCode);
616 /* Deference the Socket Context */
617 WsSockDereference(Socket);
618
619 /* Return Provider Value */
620 if (Status) return Status;
621 }
622 else
623 {
624 /* No Socket Context Found */
625 ErrorCode = WSAENOTSOCK;
626 }
627 }
628
629 /* Return with an Error */
630 SetLastError(ErrorCode);
631 return FALSE;
632 }