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