- Build fixes
[reactos.git] / dll / win32 / mswsock / msafd / socket.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 SPI
4 * FILE: lib/mswsock/lib/init.c
5 * PURPOSE: DLL Initialization
6 */
7
8 /* INCLUDES ******************************************************************/
9 #include "msafd.h"
10
11 /* DATA **********************************************************************/
12
13 /* FUNCTIONS *****************************************************************/
14
15 INT
16 WSPAPI
17 SockSocket(INT AddressFamily,
18 INT SocketType,
19 INT Protocol,
20 LPGUID ProviderId,
21 GROUP g,
22 DWORD dwFlags,
23 DWORD ProviderFlags,
24 DWORD ServiceFlags,
25 DWORD CatalogEntryId,
26 PSOCKET_INFORMATION *NewSocket)
27 {
28 INT ErrorCode;
29 UNICODE_STRING TransportName;
30 PVOID HelperDllContext;
31 PHELPER_DATA HelperData = NULL;
32 DWORD HelperEvents;
33 PFILE_FULL_EA_INFORMATION Ea = NULL;
34 PAFD_CREATE_PACKET AfdPacket;
35 SOCKET Handle = INVALID_SOCKET;
36 PSOCKET_INFORMATION Socket = NULL;
37 BOOLEAN LockInit = FALSE;
38 USHORT SizeOfPacket;
39 DWORD SizeOfEa, SocketLength;
40 OBJECT_ATTRIBUTES ObjectAttributes;
41 UNICODE_STRING DevName;
42 LARGE_INTEGER GroupData;
43 DWORD CreateOptions = 0;
44 IO_STATUS_BLOCK IoStatusBlock;
45 PWAH_HANDLE WahHandle;
46 NTSTATUS Status;
47 CHAR AfdPacketBuffer[96];
48
49 /* Initialize the transport name */
50 RtlInitUnicodeString(&TransportName, NULL);
51
52 /* Get Helper Data and Transport */
53 ErrorCode = SockGetTdiName(&AddressFamily,
54 &SocketType,
55 &Protocol,
56 ProviderId,
57 g,
58 dwFlags,
59 &TransportName,
60 &HelperDllContext,
61 &HelperData,
62 &HelperEvents);
63
64 /* Check for error */
65 if (ErrorCode != NO_ERROR) goto error;
66
67 /* Figure out the socket context structure size */
68 SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2);
69
70 /* Allocate a socket */
71 Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength);
72 if (!Socket)
73 {
74 /* Couldn't create it; we need to tell WSH so it can cleanup */
75 if (HelperEvents & WSH_NOTIFY_CLOSE)
76 {
77 HelperData->WSHNotify(HelperDllContext,
78 INVALID_SOCKET,
79 NULL,
80 NULL,
81 WSH_NOTIFY_CLOSE);
82 }
83
84 /* Fail and return */
85 ErrorCode = WSAENOBUFS;
86 goto error;
87 }
88
89 /* Initialize it */
90 RtlZeroMemory(Socket, SocketLength);
91 Socket->RefCount = 2;
92 Socket->Handle = INVALID_SOCKET;
93 Socket->SharedData.State = SocketUndefined;
94 Socket->SharedData.AddressFamily = AddressFamily;
95 Socket->SharedData.SocketType = SocketType;
96 Socket->SharedData.Protocol = Protocol;
97 Socket->ProviderId = *ProviderId;
98 Socket->HelperContext = HelperDllContext;
99 Socket->HelperData = HelperData;
100 Socket->HelperEvents = HelperEvents;
101 Socket->LocalAddress = (PVOID)(Socket + 1);
102 Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
103 Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress +
104 HelperData->MaxWSAddressLength);
105 Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
106 Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
107 Socket->SharedData.CreateFlags = dwFlags;
108 Socket->SharedData.CatalogEntryId = CatalogEntryId;
109 Socket->SharedData.ServiceFlags1 = ServiceFlags;
110 Socket->SharedData.ProviderFlags = ProviderFlags;
111 Socket->SharedData.GroupID = g;
112 Socket->SharedData.GroupType = 0;
113 Socket->SharedData.UseSAN = FALSE;
114 Socket->SanData = NULL;
115 Socket->DontUseSan = FALSE;
116
117 /* Initialize the socket lock */
118 InitializeCriticalSection(&Socket->Lock);
119 LockInit = TRUE;
120
121 /* Packet Size */
122 SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR);
123
124 /* EA Size */
125 SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH;
126
127 /* See if our stack buffer is big enough to hold it */
128 if (SizeOfEa <= sizeof(AfdPacketBuffer))
129 {
130 /* Use our stack */
131 Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer;
132 }
133 else
134 {
135 /* Allocate from heap */
136 Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa);
137 if (!Ea)
138 {
139 /* Fail */
140 ErrorCode = WSAENOBUFS;
141 goto error;
142 }
143 }
144
145 /* Set up EA */
146 Ea->NextEntryOffset = 0;
147 Ea->Flags = 0;
148 Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
149 RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1);
150 Ea->EaValueLength = SizeOfPacket;
151
152 /* Set up AFD Packet */
153 AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1);
154 AfdPacket->SizeOfTransportName = TransportName.Length;
155 RtlCopyMemory(AfdPacket->TransportName,
156 TransportName.Buffer,
157 TransportName.Length + sizeof(WCHAR));
158 AfdPacket->EndpointFlags = 0;
159
160 /* Set up Endpoint Flags */
161 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS))
162 {
163 /* Check the Socket Type */
164 if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW))
165 {
166 /* Only RAW or UDP can be Connectionless */
167 ErrorCode = WSAEINVAL;
168 goto error;
169 }
170
171 /* Set the flag for AFD */
172 AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
173 }
174
175 if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED))
176 {
177 /* Check if this is a Stream Socket */
178 if (SocketType == SOCK_STREAM)
179 {
180 /* Check if we actually support this */
181 if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM))
182 {
183 /* The Provider doesn't support Message Oriented Streams */
184 ErrorCode = WSAEINVAL;
185 goto error;
186 }
187 }
188
189 /* Set the flag for AFD */
190 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
191 }
192
193 /* If this is a Raw Socket, let AFD know */
194 if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
195
196 /* Check if we are a Multipoint Control/Data Root or Leaf */
197 if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT |
198 WSA_FLAG_MULTIPOINT_C_LEAF |
199 WSA_FLAG_MULTIPOINT_D_ROOT |
200 WSA_FLAG_MULTIPOINT_D_LEAF))
201 {
202 /* First make sure we support Multipoint */
203 if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT))
204 {
205 /* The Provider doesn't actually support Multipoint */
206 ErrorCode = WSAEINVAL;
207 goto error;
208 }
209
210 /* Set the flag for AFD */
211 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
212
213 /* Check if we are a Control Plane Root */
214 if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT)
215 {
216 /* Check if we actually support this or if we're already a leaf */
217 if ((!(Socket->SharedData.ServiceFlags1 &
218 XP1_MULTIPOINT_CONTROL_PLANE)) ||
219 ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF)))
220 {
221 ErrorCode = WSAEINVAL;
222 goto error;
223 }
224
225 /* Set the flag for AFD */
226 AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
227 }
228
229 /* Check if we a Data Plane Root */
230 if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT)
231 {
232 /* Check if we actually support this or if we're already a leaf */
233 if ((!(Socket->SharedData.ServiceFlags1 &
234 XP1_MULTIPOINT_DATA_PLANE)) ||
235 ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF)))
236 {
237 ErrorCode = WSAEINVAL;
238 goto error;
239 }
240
241 /* Set the flag for AFD */
242 AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
243 }
244 }
245
246 /* Set the group ID */
247 AfdPacket->GroupID = g;
248
249 /* Set up Object Attributes */
250 RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
251 InitializeObjectAttributes(&ObjectAttributes,
252 &DevName,
253 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
254 NULL,
255 NULL);
256
257 /* Check if we're not using Overlapped I/O */
258 if (!(dwFlags & WSA_FLAG_OVERLAPPED))
259 {
260 /* Set Synchronous I/O */
261 CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT;
262 }
263
264 /* Acquire the global lock */
265 SockAcquireRwLockShared(&SocketGlobalLock);
266
267 /* Create the Socket */
268 Status = NtCreateFile((PHANDLE)&Handle,
269 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
270 &ObjectAttributes,
271 &IoStatusBlock,
272 NULL,
273 0,
274 FILE_SHARE_READ | FILE_SHARE_WRITE,
275 FILE_OPEN_IF,
276 CreateOptions,
277 Ea,
278 SizeOfEa);
279 if (!NT_SUCCESS(Status))
280 {
281 /* Release the lock and fail */
282 SockReleaseRwLockShared(&SocketGlobalLock);
283 ErrorCode = NtStatusToSocketError(Status);
284 goto error;
285 }
286
287 /* Save Handle */
288 Socket->Handle = Handle;
289
290 /* Check if a group was given */
291 if (g != 0)
292 {
293 /* Get Group Id and Type */
294 ErrorCode = SockGetInformation(Socket,
295 AFD_INFO_GROUP_ID_TYPE,
296 NULL,
297 0,
298 NULL,
299 NULL,
300 &GroupData);
301
302 /* Save them */
303 Socket->SharedData.GroupID = GroupData.u.LowPart;
304 Socket->SharedData.GroupType = GroupData.u.HighPart;
305 }
306
307 /* Check if we need to get the window sizes */
308 if (!SockSendBufferWindow)
309 {
310 /* Get send window size */
311 SockGetInformation(Socket,
312 AFD_INFO_SEND_WINDOW_SIZE,
313 NULL,
314 0,
315 NULL,
316 &SockSendBufferWindow,
317 NULL);
318
319 /* Get receive window size */
320 SockGetInformation(Socket,
321 AFD_INFO_RECEIVE_WINDOW_SIZE,
322 NULL,
323 0,
324 NULL,
325 &SockReceiveBufferWindow,
326 NULL);
327 }
328
329 /* Save window sizes */
330 Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow;
331 Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow;
332
333 /* Insert it into our table */
334 WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext);
335
336 /* We can release the lock now */
337 SockReleaseRwLockShared(&SocketGlobalLock);
338
339 /* Check if the handles don't match for some reason */
340 if (WahHandle != &Socket->WshContext)
341 {
342 /* Do they not match? */
343 if (WahHandle)
344 {
345 /* They don't... someone must've used CloseHandle */
346 SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle);
347
348 /* Use the correct handle now */
349 WahHandle = &Socket->WshContext;
350 }
351 else
352 {
353 /* It's not that they don't match: we don't have one at all! */
354 ErrorCode = WSAENOBUFS;
355 goto error;
356 }
357 }
358
359 error:
360 /* Check if we can free the transport name */
361 if ((SocketType == SOCK_RAW) && (TransportName.Buffer))
362 {
363 /* Free it */
364 RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer);
365 }
366
367 /* Check if we have the EA from the heap */
368 if ((Ea) && (Ea != (PVOID)AfdPacketBuffer))
369 {
370 /* Free it */
371 RtlFreeHeap(SockPrivateHeap, 0, Ea);
372 }
373
374 /* Check if this is actually success */
375 if (ErrorCode != NO_ERROR)
376 {
377 /* Check if we have a socket by now */
378 if (Socket)
379 {
380 /* Tell the Helper DLL we're closing it */
381 SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE);
382
383 /* Close its handle if it's valid */
384 if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE)
385 {
386 NtClose(Socket->WshContext.Handle);
387 }
388
389 /* Delete its lock */
390 if (LockInit) DeleteCriticalSection(&Socket->Lock);
391
392 /* Remove our socket reference */
393 SockDereferenceSocket(Socket);
394
395 /* Free it */
396 RtlFreeHeap(SockPrivateHeap, 0, Socket);
397 }
398 }
399
400 /* Return Socket and error code */
401 *NewSocket = Socket;
402 return ErrorCode;
403 }
404
405 INT
406 WSPAPI
407 SockCloseSocket(IN PSOCKET_INFORMATION Socket)
408 {
409 INT ErrorCode;
410 PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData;
411 IO_STATUS_BLOCK IoStatusBlock;
412 NTSTATUS Status;
413 AFD_DISCONNECT_INFO DisconnectInfo;
414 SOCKET_STATE OldState;
415 ULONG LingerWait;
416 ULONG SendsInProgress;
417 ULONG SleepWait;
418 BOOLEAN ActiveConnect;
419
420 /* Lock the socket */
421 EnterCriticalSection(&Socket->Lock);
422
423 /* If a Close is already in Process... */
424 if (Socket->SharedData.State == SocketClosed)
425 {
426 /* Release lock and fail */
427 LeaveCriticalSection(&Socket->Lock);
428 return WSAENOTSOCK;
429 }
430
431 /* Save the old state and set the new one to closed */
432 OldState = Socket->SharedData.State;
433 Socket->SharedData.State = SocketClosed;
434
435 /* Check if the socket has an active async data */
436 ActiveConnect = (Socket->AsyncData != NULL);
437
438 /* We're done with the socket, release the lock */
439 LeaveCriticalSection(&Socket->Lock);
440
441 /*
442 * If SO_LINGER is ON and the Socket was connected or had an active async
443 * connect context, then we'll disconnect it. Note that we won't do this
444 * for connection-less (UDP/RAW) sockets or if a send shutdown is active.
445 */
446 if ((OldState == SocketConnected || ActiveConnect) &&
447 !(Socket->SharedData.SendShutdown) &&
448 !MSAFD_IS_DGRAM_SOCK(Socket) &&
449 (Socket->SharedData.LingerData.l_onoff))
450 {
451 /* We need to respect the timeout */
452 SleepWait = 100;
453 LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
454
455 /* Loop until no more sends are pending, within the timeout */
456 while (LingerWait)
457 {
458 /* Find out how many Sends are in Progress */
459 if (SockGetInformation(Socket,
460 AFD_INFO_SENDS_IN_PROGRESS,
461 NULL,
462 0,
463 NULL,
464 &SendsInProgress,
465 NULL))
466 {
467 /* Bail out if anything but NO_ERROR */
468 LingerWait = 0;
469 break;
470 }
471
472 /* Bail out if no more sends are pending */
473 if (!SendsInProgress) break;
474
475 /*
476 * We have to execute a sleep, so it's kind of like
477 * a block. If the socket is Nonblock, we cannot
478 * go on since asyncronous operation is expected
479 * and we cannot offer it
480 */
481 if (Socket->SharedData.NonBlocking)
482 {
483 /* Acquire the socket lock */
484 EnterCriticalSection(&Socket->Lock);
485
486 /* Restore the socket state */
487 Socket->SharedData.State = OldState;
488
489 /* Release the lock again */
490 LeaveCriticalSection(&Socket->Lock);
491
492 /* Fail with error code */
493 return WSAEWOULDBLOCK;
494 }
495
496 /* Now we can sleep, and decrement the linger wait */
497 /*
498 * FIXME: It seems Windows does some funky acceleration
499 * since the waiting seems to be longer and longer. I
500 * don't think this improves performance so much, so we
501 * wait a fixed time instead.
502 */
503 Sleep(SleepWait);
504 LingerWait -= SleepWait;
505 }
506
507 /*
508 * We have reached the timeout or sends are over.
509 * Disconnect if the timeout has been reached.
510 */
511 if (LingerWait <= 0)
512 {
513 /* There is no timeout, and this is an abortive disconnect */
514 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
515 DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT;
516
517 /* Send IOCTL */
518 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
519 ThreadData->EventHandle,
520 NULL,
521 NULL,
522 &IoStatusBlock,
523 IOCTL_AFD_DISCONNECT,
524 &DisconnectInfo,
525 sizeof(DisconnectInfo),
526 NULL,
527 0);
528 /* Check if the operation is pending */
529 if (Status == STATUS_PENDING)
530 {
531 /* Wait for completion */
532 SockWaitForSingleObject(ThreadData->EventHandle,
533 Socket->Handle,
534 !Socket->SharedData.LingerData.l_onoff ?
535 NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK,
536 NO_TIMEOUT);
537
538 /* Get new status */
539 Status = IoStatusBlock.Status;
540 }
541
542 /* We actually accept errors, unless the driver wasn't ready */
543 if (Status == STATUS_DEVICE_NOT_READY)
544 {
545 /* This is the equivalent of a WOULDBLOCK, which we fail */
546 /* Acquire the socket lock */
547 EnterCriticalSection(&Socket->Lock);
548
549 /* Restore the socket state */
550 Socket->SharedData.State = OldState;
551
552 /* Release the lock again */
553 LeaveCriticalSection(&Socket->Lock);
554
555 /* Fail with error code */
556 return WSAEWOULDBLOCK;
557 }
558 }
559 }
560
561 /* Acquire the global lock to protect the handle table */
562 SockAcquireRwLockShared(&SocketGlobalLock);
563
564 /* Protect the socket too */
565 EnterCriticalSection(&Socket->Lock);
566
567 /* Notify the Helper DLL of Socket Closure */
568 ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE);
569
570 /* Cleanup Time! */
571 Socket->HelperContext = NULL;
572 Socket->SharedData.AsyncDisabledEvents = -1;
573 if (Socket->TdiAddressHandle)
574 {
575 /* Close and forget the handle */
576 NtClose(Socket->TdiAddressHandle);
577 Socket->TdiAddressHandle = NULL;
578 }
579 if (Socket->TdiConnectionHandle)
580 {
581 /* Close and forget the handle */
582 NtClose(Socket->TdiConnectionHandle);
583 Socket->TdiConnectionHandle = NULL;
584 }
585
586 /* Remove the handle from the table */
587 ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext);
588 if (ErrorCode == NO_ERROR)
589 {
590 /* Close the socket's handle */
591 NtClose(Socket->WshContext.Handle);
592
593 /* Dereference the socket */
594 SockDereferenceSocket(Socket);
595 }
596 else
597 {
598 /* This isn't a socket anymore, or something */
599 ErrorCode = WSAENOTSOCK;
600 }
601
602 /* Release both locks */
603 LeaveCriticalSection(&Socket->Lock);
604 SockReleaseRwLockShared(&SocketGlobalLock);
605
606 /* Return success */
607 return ErrorCode;
608 }
609
610 SOCKET
611 WSPAPI
612 WSPSocket(INT AddressFamily,
613 INT SocketType,
614 INT Protocol,
615 LPWSAPROTOCOL_INFOW lpProtocolInfo,
616 GROUP g,
617 DWORD dwFlags,
618 LPINT lpErrno)
619 {
620 DWORD CatalogId;
621 SOCKET Handle = INVALID_SOCKET;
622 INT ErrorCode;
623 DWORD ServiceFlags, ProviderFlags;
624 PWINSOCK_TEB_DATA ThreadData;
625 PSOCKET_INFORMATION Socket;
626 GUID ProviderId;
627
628 /* Enter prolog */
629 ErrorCode = SockEnterApiFast(&ThreadData);
630 if (ErrorCode != NO_ERROR)
631 {
632 /* Fail */
633 *lpErrno = ErrorCode;
634 return INVALID_SOCKET;
635 }
636
637 /* Get the catalog ID */
638 CatalogId = lpProtocolInfo->dwCatalogEntryId;
639
640 /* Check if this is a duplication */
641 if(lpProtocolInfo->dwProviderReserved)
642 {
643 /* Get the duplicate handle */
644 Handle = (SOCKET)lpProtocolInfo->dwProviderReserved;
645
646 /* Get our structure for it */
647 Socket = SockFindAndReferenceSocket(Handle, TRUE);
648 if(Socket)
649 {
650 /* Tell Winsock about it */
651 Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId,
652 Handle,
653 &ErrorCode);
654 /* Check if we got an invalid handle back */
655 if(Socket->Handle == INVALID_SOCKET)
656 {
657 /* Restore it for the error path */
658 Socket->Handle = Handle;
659 }
660 }
661 else
662 {
663 /* The duplicate handle is invalid */
664 ErrorCode = WSAEINVAL;
665 }
666
667 /* Fail */
668 goto error;
669 }
670
671 /* See if the address family should be recovered from the protocl info */
672 if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO)
673 {
674 /* Use protocol info data */
675 AddressFamily = lpProtocolInfo->iAddressFamily;
676 }
677
678 /* See if the address family should be recovered from the protocl info */
679 if(!SocketType || SocketType == FROM_PROTOCOL_INFO )
680 {
681 /* Use protocol info data */
682 SocketType = lpProtocolInfo->iSocketType;
683 }
684
685 /* See if the address family should be recovered from the protocl info */
686 if(Protocol == FROM_PROTOCOL_INFO)
687 {
688 /* Use protocol info data */
689 Protocol = lpProtocolInfo->iProtocol;
690 }
691
692 /* Save the service, provider flags and provider ID */
693 ServiceFlags = lpProtocolInfo->dwServiceFlags1;
694 ProviderFlags = lpProtocolInfo->dwProviderFlags;
695 ProviderId = lpProtocolInfo->ProviderId;
696
697 /* Create the actual socket */
698 ErrorCode = SockSocket(AddressFamily,
699 SocketType,
700 Protocol,
701 &ProviderId,
702 g,
703 dwFlags,
704 ProviderFlags,
705 ServiceFlags,
706 CatalogId,
707 &Socket);
708 if (ErrorCode == ERROR_SUCCESS)
709 {
710 /* Acquire the socket lock */
711 EnterCriticalSection(&Socket->Lock);
712
713 /* Set status to opened */
714 Socket->SharedData.State = SocketOpen;
715
716 /* Create the Socket Context */
717 ErrorCode = SockSetHandleContext(Socket);
718 if (ErrorCode != NO_ERROR)
719 {
720 /* Release the lock, close the socket and fail */
721 LeaveCriticalSection(&Socket->Lock);
722 SockCloseSocket(Socket);
723 goto error;
724 }
725
726 /* Notify Winsock */
727 Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId,
728 (SOCKET)Socket->WshContext.Handle,
729 &ErrorCode);
730
731 /* Does Winsock not like it? */
732 if (Handle == INVALID_SOCKET)
733 {
734 /* Release the lock, close the socket and fail */
735 LeaveCriticalSection(&Socket->Lock);
736 SockCloseSocket(Socket);
737 goto error;
738 }
739
740 /* Release the lock */
741 LeaveCriticalSection(&Socket->Lock);
742 }
743
744 error:
745 /* Write return code */
746 *lpErrno = ErrorCode;
747
748 /* Check if we have a socket and dereference it */
749 if (Socket) SockDereferenceSocket(Socket);
750
751 /* Return handle */
752 return Handle;
753 }
754
755 INT
756 WSPAPI
757 WSPCloseSocket(IN SOCKET Handle,
758 OUT LPINT lpErrno)
759 {
760 INT ErrorCode;
761 PSOCKET_INFORMATION Socket;
762 PWINSOCK_TEB_DATA ThreadData;
763
764 /* Enter prolog */
765 ErrorCode = SockEnterApiFast(&ThreadData);
766 if (ErrorCode != NO_ERROR)
767 {
768 /* Fail */
769 *lpErrno = ErrorCode;
770 return SOCKET_ERROR;
771 }
772
773 /* Get the socket structure */
774 Socket = SockFindAndReferenceSocket(Handle, TRUE);
775 if (!Socket)
776 {
777 /* Fail */
778 *lpErrno = WSAENOTSOCK;
779 return SOCKET_ERROR;
780 }
781
782 /* Close it */
783 ErrorCode = SockCloseSocket(Socket);
784
785 /* Remove the final reference */
786 SockDereferenceSocket(Socket);
787
788 /* Check if we got here by error */
789 if (ErrorCode != NO_ERROR)
790 {
791 /* Fail */
792 *lpErrno = ErrorCode;
793 return SOCKET_ERROR;
794 }
795
796 /* Return success */
797 return NO_ERROR;
798 }
799