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 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 } 644