1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32/src/socklife.c 5 * PURPOSE: Socket Lifetime 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 SOCKET 22 WSAAPI 23 accept(IN SOCKET s, 24 OUT LPSOCKADDR addr, 25 OUT INT FAR* addrlen) 26 { 27 /* Let WSA do it */ 28 return WSAAccept(s, addr, addrlen, NULL, 0); 29 } 30 31 /* 32 * @implemented 33 */ 34 INT 35 WSAAPI 36 bind(IN SOCKET s, 37 IN CONST struct sockaddr *name, 38 IN INT namelen) 39 { 40 PWSSOCKET Socket; 41 INT Status; 42 INT ErrorCode; 43 DPRINT("bind: %lx, %p, %lx\n", s, name, namelen); 44 45 /* Check for WSAStartup */ 46 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 47 { 48 /* Get the Socket Context */ 49 if ((Socket = WsSockGetSocket(s))) 50 { 51 if (name && (namelen >= sizeof(*name))) 52 { 53 /* Make the call */ 54 Status = Socket->Provider->Service.lpWSPBind(s, 55 name, 56 namelen, 57 &ErrorCode); 58 /* Deference the Socket Context */ 59 WsSockDereference(Socket); 60 61 /* Return Provider Value */ 62 if (Status == ERROR_SUCCESS) return Status; 63 64 /* If everything seemed fine, then the WSP call failed itself */ 65 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE; 66 } 67 else 68 { 69 /* Deference the Socket Context */ 70 WsSockDereference(Socket); 71 72 /* name or namelen not valid */ 73 ErrorCode = WSAEFAULT; 74 } 75 } 76 else 77 { 78 /* No Socket Context Found */ 79 ErrorCode = WSAENOTSOCK; 80 } 81 } 82 83 /* Return with an Error */ 84 SetLastError(ErrorCode); 85 return SOCKET_ERROR; 86 } 87 88 /* 89 * @implemented 90 */ 91 INT 92 WSAAPI 93 closesocket(IN SOCKET s) 94 { 95 PWSSOCKET Socket; 96 INT Status; 97 INT ErrorCode; 98 DPRINT("closesocket: %lx\n", s); 99 100 /* Check for WSAStartup */ 101 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) 102 { 103 /* Get the Socket Context */ 104 if ((Socket = WsSockGetSocket(s))) 105 { 106 /* Make the call */ 107 Status = Socket->Provider->Service.lpWSPCloseSocket(s, &ErrorCode); 108 109 /* Check if this is a provider socket */ 110 if ((Status == ERROR_SUCCESS) && (Socket->IsProvider)) 111 { 112 /* Disassociate the handle */ 113 if (WsSockDisassociateHandle(Socket) == ERROR_SUCCESS) 114 { 115 /* Deference the Socket Context */ 116 WsSockDereference(Socket); 117 } 118 119 /* Remove the last reference */ 120 WsSockDereference(Socket); 121 122 /* Return success if everything is OK */ 123 if (ErrorCode == ERROR_SUCCESS) return ErrorCode; 124 } 125 } 126 else 127 { 128 /* No Socket Context Found */ 129 ErrorCode = WSAENOTSOCK; 130 } 131 } 132 133 /* Return with an Error */ 134 SetLastError(ErrorCode); 135 return SOCKET_ERROR; 136 } 137 138 /* 139 * @implemented 140 */ 141 SOCKET 142 WSAAPI 143 socket(IN INT af, 144 IN INT type, 145 IN INT protocol) 146 { 147 PWSPROCESS Process; 148 PWSTHREAD Thread; 149 DWORD Flags = 0; 150 INT ErrorCode; 151 DPRINT("socket: %lx, %lx, %lx\n", af, type, protocol); 152 153 /* Enter prolog */ 154 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 155 { 156 /* Fail here */ 157 SetLastError(ErrorCode); 158 return INVALID_SOCKET; 159 } 160 161 /* Check the current open type and use overlapped if it's default */ 162 if (!Thread->OpenType) Flags = WSA_FLAG_OVERLAPPED; 163 164 /* Make the protocol negative if this is NETBIOS */ 165 if ((af == AF_NETBIOS) && (protocol > 0)) protocol *= -1; 166 167 /* Now let WSA handle it */ 168 return WSASocketW(af, type, protocol, NULL, 0, Flags); 169 } 170 171 /* 172 * @unimplemented 173 */ 174 INT 175 WSPAPI 176 WPUCloseSocketHandle(IN SOCKET s, 177 OUT LPINT lpErrno) 178 { 179 UNIMPLEMENTED; 180 return 0; 181 } 182 183 /* 184 * @unimplemented 185 */ 186 SOCKET 187 WSPAPI 188 WPUCreateSocketHandle(IN DWORD dwCatalogEntryId, 189 IN DWORD_PTR dwContext, 190 OUT LPINT lpErrno) 191 { 192 UNIMPLEMENTED; 193 return (SOCKET)0; 194 } 195 196 /* 197 * @implemented 198 */ 199 SOCKET 200 WSPAPI 201 WPUModifyIFSHandle(IN DWORD dwCatalogEntryId, 202 IN SOCKET ProposedHandle, 203 OUT LPINT lpErrno) 204 { 205 SOCKET Handle = INVALID_SOCKET; 206 DWORD ErrorCode = ERROR_SUCCESS; 207 PWSPROCESS Process; 208 PTCATALOG Catalog; 209 PTCATALOG_ENTRY Entry; 210 PWSSOCKET Socket; 211 DPRINT("WPUModifyIFSHandle: %lx, %lx\n", dwCatalogEntryId, ProposedHandle); 212 213 /* Get the current process */ 214 if ((Process = WsGetProcess())) 215 { 216 /* Get the Transport Catalog */ 217 if ((Catalog = WsProcGetTCatalog(Process))) 218 { 219 /* Get the entry for this ID */ 220 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 221 dwCatalogEntryId, 222 &Entry); 223 /* Check for success */ 224 if (ErrorCode == ERROR_SUCCESS) 225 { 226 /* Create a socket object */ 227 if ((Socket = WsSockAllocate())) 228 { 229 /* Initialize it */ 230 WsSockInitialize(Socket, Entry); 231 232 /* Associate it */ 233 ErrorCode = WsSockAssociateHandle(Socket, 234 ProposedHandle, 235 TRUE); 236 /* Check for success */ 237 if (ErrorCode == ERROR_SUCCESS) 238 { 239 /* Return */ 240 Handle = ProposedHandle; 241 *lpErrno = ERROR_SUCCESS; 242 } 243 else 244 { 245 /* Fail */ 246 WsSockDereference(Socket); 247 *lpErrno = ErrorCode; 248 } 249 250 /* Dereference the extra count */ 251 WsSockDereference(Socket); 252 } 253 else 254 { 255 /* No memory to allocate a socket */ 256 *lpErrno = WSAENOBUFS; 257 } 258 259 /* Dereference the catalog entry */ 260 WsTcEntryDereference(Entry); 261 } 262 else 263 { 264 /* Entry not found */ 265 *lpErrno = ErrorCode; 266 } 267 } 268 else 269 { 270 /* Catalog not found */ 271 *lpErrno = WSANOTINITIALISED; 272 } 273 } 274 else 275 { 276 /* Process not ready */ 277 *lpErrno = WSANOTINITIALISED; 278 } 279 280 /* Return */ 281 return Handle; 282 } 283 284 /* 285 * @unimplemented 286 */ 287 INT 288 WSPAPI 289 WPUQuerySocketHandleContext(IN SOCKET s, 290 OUT PDWORD_PTR lpContext, 291 OUT LPINT lpErrno) 292 { 293 UNIMPLEMENTED; 294 return 0; 295 } 296 297 /* 298 * @implemented 299 */ 300 SOCKET 301 WSAAPI 302 WSAAccept(IN SOCKET s, 303 OUT LPSOCKADDR addr, 304 IN OUT LPINT addrlen, 305 IN LPCONDITIONPROC lpfnCondition, 306 IN DWORD_PTR dwCallbackData) 307 { 308 PWSPROCESS Process; 309 PWSTHREAD Thread; 310 PWSSOCKET Socket; 311 DWORD OpenType; 312 INT ErrorCode; 313 SOCKET Status; 314 DPRINT("WSAAccept: %lx, %lx, %lx, %p\n", s, addr, addrlen, lpfnCondition); 315 316 /* Enter prolog */ 317 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS) 318 { 319 /* Get the Socket Context */ 320 if ((Socket = WsSockGetSocket(s))) 321 { 322 /* Get the old open type and set new one */ 323 OpenType = Thread->OpenType; 324 Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT; 325 326 /* Make the call */ 327 Status = Socket->Provider->Service.lpWSPAccept(s, 328 addr, 329 addrlen, 330 lpfnCondition, 331 dwCallbackData, 332 &ErrorCode); 333 /* Restore open type */ 334 Thread->OpenType = OpenType; 335 336 /* Deference the Socket Context */ 337 WsSockDereference(Socket); 338 339 /* Check if we got a valid socket */ 340 if (Status != INVALID_SOCKET) 341 { 342 /* Check if we got a new socket */ 343 if (Status != s) 344 { 345 /* Add a new reference */ 346 WsSockAddApiReference(Status); 347 } 348 349 /* Return */ 350 return Status; 351 } 352 } 353 else 354 { 355 /* No Socket Context Found */ 356 ErrorCode = WSAENOTSOCK; 357 } 358 } 359 360 /* Return with an Error */ 361 SetLastError(ErrorCode); 362 return INVALID_SOCKET; 363 } 364 365 /* 366 * @implemented 367 */ 368 SOCKET 369 WSAAPI 370 WSAJoinLeaf(IN SOCKET s, 371 IN CONST struct sockaddr *name, 372 IN INT namelen, 373 IN LPWSABUF lpCallerData, 374 OUT LPWSABUF lpCalleeData, 375 IN LPQOS lpSQOS, 376 IN LPQOS lpGQOS, 377 IN DWORD dwFlags) 378 { 379 PWSPROCESS Process; 380 PWSTHREAD Thread; 381 PWSSOCKET Socket; 382 DWORD OpenType; 383 INT ErrorCode; 384 SOCKET Status; 385 DPRINT("WSAJoinLeaf: %lx, %lx, %lx\n", s, name, namelen); 386 387 /* Enter prolog */ 388 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS) 389 { 390 /* Get the Socket Context */ 391 if ((Socket = WsSockGetSocket(s))) 392 { 393 /* Get the old open type and set new one */ 394 OpenType = Thread->OpenType; 395 Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT; 396 397 /* Make the call */ 398 Status = Socket->Provider->Service.lpWSPJoinLeaf(s, 399 name, 400 namelen, 401 lpCallerData, 402 lpCalleeData, 403 lpSQOS, 404 lpGQOS, 405 dwFlags, 406 &ErrorCode); 407 /* Restore open type */ 408 Thread->OpenType = OpenType; 409 410 /* Deference the Socket Context */ 411 WsSockDereference(Socket); 412 413 /* Check if we got a valid socket */ 414 if (Status != INVALID_SOCKET) 415 { 416 /* Check if we got a new socket */ 417 if (Status != s) 418 { 419 /* Add a new reference */ 420 WsSockAddApiReference(Status); 421 } 422 423 /* Return */ 424 return Status; 425 } 426 } 427 else 428 { 429 /* No Socket Context Found */ 430 ErrorCode = WSAENOTSOCK; 431 } 432 } 433 434 /* Return with an Error */ 435 SetLastError(ErrorCode); 436 return INVALID_SOCKET; 437 } 438 439 /* 440 * @implemented 441 */ 442 SOCKET 443 WSAAPI 444 WSASocketA(IN INT af, 445 IN INT type, 446 IN INT protocol, 447 IN LPWSAPROTOCOL_INFOA lpProtocolInfo, 448 IN GROUP g, 449 IN DWORD dwFlags) 450 { 451 WSAPROTOCOL_INFOW ProtocolInfoW; 452 LPWSAPROTOCOL_INFOW p = &ProtocolInfoW; 453 454 /* Convert Protocol Info to Wide */ 455 if (lpProtocolInfo) 456 { 457 /* Copy the Data */ 458 memcpy(&ProtocolInfoW, 459 lpProtocolInfo, 460 sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1)); 461 462 /* Convert the String */ 463 MultiByteToWideChar(CP_ACP, 464 0, 465 lpProtocolInfo->szProtocol, 466 -1, 467 ProtocolInfoW.szProtocol, 468 sizeof(ProtocolInfoW.szProtocol) / sizeof(WCHAR)); 469 } 470 else 471 { 472 /* No Protocol Info Specified */ 473 p = NULL; 474 } 475 476 /* Call the Unicode Function */ 477 return WSASocketW(af, 478 type, 479 protocol, 480 p, 481 g, 482 dwFlags); 483 } 484 485 /* 486 * @implemented 487 */ 488 SOCKET 489 WSAAPI 490 WSASocketW(IN INT af, 491 IN INT type, 492 IN INT protocol, 493 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 494 IN GROUP g, 495 IN DWORD dwFlags) 496 { 497 PWSPROCESS Process; 498 PWSTHREAD Thread; 499 INT ErrorCode; 500 PTCATALOG Catalog; 501 DWORD CatalogId; 502 PTCATALOG_ENTRY CatalogEntry; 503 LPWSAPROTOCOL_INFOW ProtocolInfo; 504 DWORD OpenType; 505 SOCKET Status = INVALID_SOCKET; 506 DPRINT("WSASocketW: %lx, %lx, %lx, %p\n", af, type, protocol, lpProtocolInfo); 507 508 /* Enter prolog */ 509 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 510 { 511 /* Fail now */ 512 SetLastError(ErrorCode); 513 return INVALID_SOCKET; 514 } 515 516 /* Get the catalog */ 517 Catalog = WsProcGetTCatalog(Process); 518 519 /* Find a Provider for the Catalog ID */ 520 if (lpProtocolInfo) 521 { 522 /* Get the catalog ID */ 523 CatalogId = lpProtocolInfo->dwCatalogEntryId; 524 525 /* Get the Catalog Entry */ 526 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 527 CatalogId, 528 &CatalogEntry); 529 } 530 else 531 { 532 /* No ID */ 533 CatalogId = 0; 534 535 DoLookup: 536 /* Get the Catalog Data from the Socket Info */ 537 ErrorCode = WsTcGetEntryFromTriplet(Catalog, 538 af, 539 type, 540 protocol, 541 CatalogId, 542 &CatalogEntry); 543 } 544 545 /* Check for Success */ 546 if (ErrorCode == ERROR_SUCCESS) 547 { 548 /* Use the default Protocol Info if none given */ 549 ProtocolInfo = lpProtocolInfo ? lpProtocolInfo : &CatalogEntry->ProtocolInfo; 550 551 /* Save the open type and set new one */ 552 OpenType = Thread->OpenType; 553 Thread->OpenType = (dwFlags & WSA_FLAG_OVERLAPPED) ? 554 0 : SO_SYNCHRONOUS_NONALERT; 555 556 /* Call the Provider to create the Socket */ 557 Status = CatalogEntry->Provider->Service.lpWSPSocket(af, 558 type, 559 protocol, 560 ProtocolInfo, 561 g, 562 dwFlags, 563 &ErrorCode); 564 /* Restore open type */ 565 Thread->OpenType = OpenType; 566 567 /* Get the catalog ID now, and dereference */ 568 CatalogId = ProtocolInfo->dwCatalogEntryId; 569 WsTcEntryDereference(CatalogEntry); 570 571 /* Did we fail with WSAEINPROGRESS and had no specific provider? */ 572 if ((Status == INVALID_SOCKET) && 573 (ErrorCode == WSAEINPROGRESS) && 574 !(lpProtocolInfo)) 575 { 576 /* In that case, restart the lookup from this ID */ 577 goto DoLookup; 578 } 579 580 /* Check if we got a valid socket */ 581 if (Status != INVALID_SOCKET) 582 { 583 /* Add an API reference and return */ 584 WsSockAddApiReference(Status); 585 return Status; 586 } 587 } 588 589 /* Return with an Error */ 590 SetLastError(ErrorCode); 591 return INVALID_SOCKET; 592 } 593