- New winsock (part 2 of x)
[reactos.git] / dll / win32 / mswsock / msafd / send.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 WSPSend(SOCKET Handle,
18 LPWSABUF lpBuffers,
19 DWORD dwBufferCount,
20 LPDWORD lpNumberOfBytesSent,
21 DWORD iFlags,
22 LPWSAOVERLAPPED lpOverlapped,
23 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
24 LPWSATHREADID lpThreadId,
25 LPINT lpErrno)
26 {
27 PIO_STATUS_BLOCK IoStatusBlock;
28 IO_STATUS_BLOCK DummyIoStatusBlock;
29 AFD_SEND_INFO SendInfo;
30 NTSTATUS Status;
31 PVOID APCContext;
32 PVOID ApcFunction;
33 HANDLE Event;
34 PWINSOCK_TEB_DATA ThreadData;
35 PSOCKET_INFORMATION Socket;
36 INT ErrorCode;
37 BOOLEAN ReturnValue;
38
39 /* Enter prolog */
40 ErrorCode = SockEnterApiFast(&ThreadData);
41 if (ErrorCode != NO_ERROR)
42 {
43 /* Fail */
44 *lpErrno = ErrorCode;
45 return SOCKET_ERROR;
46 }
47
48 /* Set up the Receive Structure */
49 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
50 SendInfo.BufferCount = dwBufferCount;
51 SendInfo.TdiFlags = 0;
52 SendInfo.AfdFlags = 0;
53
54 /* Set the TDI Flags */
55 if (iFlags)
56 {
57 /* Check for valid flags */
58 if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL)))
59 {
60 /* Fail */
61 ErrorCode = WSAEOPNOTSUPP;
62 goto error;
63 }
64
65 /* Check if OOB is being used */
66 if (iFlags & MSG_OOB)
67 {
68 /* Use Expedited Send for OOB */
69 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
70 }
71
72 /* Use Partial Send if enabled */
73 if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
74 }
75
76 /* Verifiy if we should use APC */
77 if (!lpOverlapped)
78 {
79 /* Not using Overlapped structure, so use normal blocking on event */
80 APCContext = NULL;
81 ApcFunction = NULL;
82 Event = ThreadData->EventHandle;
83 IoStatusBlock = &DummyIoStatusBlock;
84 }
85 else
86 {
87 /* Using apc, check if we have a completion routine */
88 if (!lpCompletionRoutine)
89 {
90 /* No need for APC */
91 APCContext = lpOverlapped;
92 ApcFunction = NULL;
93 Event = lpOverlapped->hEvent;
94 }
95 else
96 {
97 /* Use APC */
98 ApcFunction = SockIoCompletion;
99 APCContext = lpCompletionRoutine;
100 Event = NULL;
101
102 /* Skip Fast I/O */
103 SendInfo.AfdFlags = AFD_SKIP_FIO;
104 }
105
106 /* Use the overlapped's structure buffer for the I/O Status Block */
107 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
108
109 /* Make this an overlapped I/O in AFD */
110 SendInfo.AfdFlags |= AFD_OVERLAPPED;
111 }
112
113 /* Set is as Pending for now */
114 IoStatusBlock->Status = STATUS_PENDING;
115
116 /* Send IOCTL */
117 Status = NtDeviceIoControlFile((HANDLE)Handle,
118 Event,
119 ApcFunction,
120 APCContext,
121 IoStatusBlock,
122 IOCTL_AFD_SEND,
123 &SendInfo,
124 sizeof(SendInfo),
125 NULL,
126 0);
127
128 /* Increase the pending APC Count if we're using an APC */
129 if (!NT_ERROR(Status) && ApcFunction)
130 {
131 ThreadData->PendingAPCs++;
132 InterlockedIncrement(&SockProcessPendingAPCCount);
133 }
134
135 /* Wait for completition if not overlapped */
136 if ((Status == STATUS_PENDING) && !(lpOverlapped))
137 {
138 /* Wait for completion */
139 ReturnValue = SockWaitForSingleObject(Event,
140 Handle,
141 MAYBE_BLOCKING_HOOK,
142 SEND_TIMEOUT);
143
144 /* Check if the wait was successful */
145 if (ReturnValue)
146 {
147 /* Get new status */
148 Status = IoStatusBlock->Status;
149 }
150 else
151 {
152 /* Cancel the I/O */
153 SockCancelIo(Handle);
154 Status = STATUS_IO_TIMEOUT;
155 }
156 }
157
158 /* Check status */
159 switch (Status)
160 {
161 /* Success */
162 case STATUS_SUCCESS:
163 break;
164
165 /* Pending I/O */
166 case STATUS_PENDING:
167 ErrorCode = WSA_IO_PENDING;
168 goto error;
169
170 /* Other NT Error */
171 default:
172 if (!NT_SUCCESS(Status))
173 {
174 /* Fail */
175 ErrorCode = NtStatusToSocketError(Status);
176 goto error;
177 }
178 break;
179 }
180
181 /* Return the number of bytes sent */
182 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
183
184 error:
185
186 /* Check if async select was active and this blocked */
187 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
188 {
189 /* Get the socket */
190 Socket = SockFindAndReferenceSocket(Handle, TRUE);
191 if (Socket)
192 {
193 /* Lock it */
194 EnterCriticalSection(&Socket->Lock);
195
196 /* Re-enable the regular write event */
197 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
198
199 /* Unlock and dereference socket */
200 LeaveCriticalSection(&Socket->Lock);
201 SockDereferenceSocket(Socket);
202 }
203 }
204
205 /* Check for error */
206 if (ErrorCode != NO_ERROR)
207 {
208 /* Fail */
209 *lpErrno = ErrorCode;
210 return SOCKET_ERROR;
211 }
212
213 /* Return success */
214 return NO_ERROR;
215 }
216
217 INT
218 WSPAPI
219 WSPSendTo(SOCKET Handle,
220 LPWSABUF lpBuffers,
221 DWORD dwBufferCount,
222 LPDWORD lpNumberOfBytesSent,
223 DWORD iFlags,
224 const struct sockaddr *SocketAddress,
225 INT SocketAddressLength,
226 LPWSAOVERLAPPED lpOverlapped,
227 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
228 LPWSATHREADID lpThreadId,
229 LPINT lpErrno)
230 {
231 PIO_STATUS_BLOCK IoStatusBlock;
232 IO_STATUS_BLOCK DummyIoStatusBlock;
233 AFD_SEND_INFO_UDP SendInfo;
234 NTSTATUS Status;
235 PVOID APCContext;
236 PVOID ApcFunction;
237 HANDLE Event;
238 PWINSOCK_TEB_DATA ThreadData;
239 PSOCKET_INFORMATION Socket;
240 INT ErrorCode;
241 INT ReturnValue;
242 CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) +
243 MAX_TDI_ADDRESS_LENGTH];
244 PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer;
245 ULONG TdiAddressSize;
246 INT SockaddrLength;
247 PSOCKADDR Sockaddr;
248 SOCKADDR_INFO SocketInfo;
249
250 /* Enter prolog */
251 ErrorCode = SockEnterApiFast(&ThreadData);
252 if (ErrorCode != NO_ERROR)
253 {
254 /* Fail */
255 *lpErrno = ErrorCode;
256 return SOCKET_ERROR;
257 }
258
259 /* Get the socket structure */
260 Socket = SockFindAndReferenceSocket(Handle, TRUE);
261 if (!Socket)
262 {
263 /* Fail */
264 ErrorCode = WSAENOTSOCK;
265 goto error;
266 }
267
268 /*
269 * Check if this isn't a datagram socket or if it's a connected socket
270 * without an address
271 */
272 if (!MSAFD_IS_DGRAM_SOCK(Socket) ||
273 ((Socket->SharedData.State == SocketConnected) &&
274 (!SocketAddress || !SocketAddressLength)))
275 {
276 /* Call WSPSend instead */
277 SockDereferenceSocket(Socket);
278 return WSPSend(Handle,
279 lpBuffers,
280 dwBufferCount,
281 lpNumberOfBytesSent,
282 iFlags,
283 lpOverlapped,
284 lpCompletionRoutine,
285 lpThreadId,
286 lpErrno);
287 }
288
289 /* If the socket isn't connected, we need an address*/
290 if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress))
291 {
292 /* Fail */
293 ErrorCode = WSAENOTCONN;
294 goto error;
295 }
296
297 /* Validate length */
298 if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength)
299 {
300 /* Fail */
301 ErrorCode = WSAEFAULT;
302 goto error;
303 }
304
305 /* Verify flags */
306 if (iFlags & ~MSG_DONTROUTE)
307 {
308 /* Fail */
309 ErrorCode = WSAEOPNOTSUPP;
310 goto error;
311 }
312
313 /* Make sure send shutdown isn't active */
314 if (Socket->SharedData.SendShutdown)
315 {
316 /* Fail */
317 ErrorCode = WSAESHUTDOWN;
318 goto error;
319 }
320
321 /* Make sure address families match */
322 if (Socket->SharedData.AddressFamily != SocketAddress->sa_family)
323 {
324 /* Fail */
325 ErrorCode = WSAEOPNOTSUPP;
326 goto error;
327 }
328
329 /* Check if broadcast is enabled */
330 if (!Socket->SharedData.Broadcast)
331 {
332 /* The caller might want to enable it; get the Sockaddr type */
333 ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress,
334 SocketAddressLength,
335 &SocketInfo);
336 if (ErrorCode != NO_ERROR) goto error;
337
338 /* Check if this is a broadcast attempt */
339 if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast)
340 {
341 /* The socket won't allow it */
342 ErrorCode = WSAEACCES;
343 goto error;
344 }
345 }
346
347 /* Check if this socket isn't bound yet */
348 if (Socket->SharedData.State == SocketOpen)
349 {
350 /* Check if we can request the wildcard address */
351 if (Socket->HelperData->WSHGetWildcardSockaddr)
352 {
353 /* Allocate a new Sockaddr */
354 SockaddrLength = Socket->HelperData->MaxWSAddressLength;
355 Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength);
356 if (!Sockaddr)
357 {
358 /* Fail */
359 ErrorCode = WSAENOBUFS;
360 goto error;
361 }
362
363 /* Get the wildcard sockaddr */
364 ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
365 Sockaddr,
366 &SockaddrLength);
367 if (ErrorCode != NO_ERROR)
368 {
369 /* Free memory and fail */
370 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
371 goto error;
372 }
373
374 /* Lock the socket */
375 EnterCriticalSection(&Socket->Lock);
376
377 /* Make sure it's still unbound */
378 if (Socket->SharedData.State == SocketOpen)
379 {
380 /* Bind it */
381 ReturnValue = WSPBind(Handle,
382 Sockaddr,
383 SockaddrLength,
384 &ErrorCode);
385 }
386 else
387 {
388 /* It's bound now, fake success */
389 ReturnValue = NO_ERROR;
390 }
391
392 /* Release the lock and free memory */
393 LeaveCriticalSection(&Socket->Lock);
394 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
395
396 /* Check if we failed */
397 if (ReturnValue == SOCKET_ERROR) goto error;
398 }
399 else
400 {
401 /* Unbound socket, but can't get the wildcard. Fail */
402 ErrorCode = WSAEINVAL;
403 goto error;
404 }
405 }
406
407 /* Check how long the TDI Address is */
408 TdiAddressSize = Socket->HelperData->MaxTDIAddressLength;
409
410 /* See if it can fit in the stack */
411 if (TdiAddressSize > sizeof(AddressBuffer))
412 {
413 /* Allocate from heap */
414 TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize);
415 if (!TdiAddress)
416 {
417 /* Fail */
418 ErrorCode = WSAENOBUFS;
419 goto error;
420 }
421 }
422
423 /* Build the TDI Address */
424 ErrorCode = SockBuildTdiAddress(TdiAddress,
425 (PSOCKADDR)SocketAddress,
426 min(SocketAddressLength,
427 Socket->HelperData->MaxWSAddressLength));
428 if (ErrorCode != NO_ERROR) goto error;
429
430 /* Set up the Send Structure */
431 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
432 SendInfo.BufferCount = dwBufferCount;
433 SendInfo.AfdFlags = 0;
434 SendInfo.TdiConnection.RemoteAddress = TdiAddress;
435 SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize;
436
437 /* Verifiy if we should use APC */
438 if (!lpOverlapped)
439 {
440 /* Not using Overlapped structure, so use normal blocking on event */
441 APCContext = NULL;
442 ApcFunction = NULL;
443 Event = ThreadData->EventHandle;
444 IoStatusBlock = &DummyIoStatusBlock;
445 }
446 else
447 {
448 /* Using apc, check if we have a completion routine */
449 if (!lpCompletionRoutine)
450 {
451 /* No need for APC */
452 APCContext = lpOverlapped;
453 ApcFunction = NULL;
454 Event = lpOverlapped->hEvent;
455 }
456 else
457 {
458 /* Use APC */
459 ApcFunction = SockIoCompletion;
460 APCContext = lpCompletionRoutine;
461 Event = NULL;
462
463 /* Skip Fast I/O */
464 SendInfo.AfdFlags = AFD_SKIP_FIO;
465 }
466
467 /* Use the overlapped's structure buffer for the I/O Status Block */
468 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
469
470 /* Make this an overlapped I/O in AFD */
471 SendInfo.AfdFlags |= AFD_OVERLAPPED;
472 }
473
474 /* Set is as Pending for now */
475 IoStatusBlock->Status = STATUS_PENDING;
476
477 /* Send IOCTL */
478 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
479 Event,
480 ApcFunction,
481 APCContext,
482 IoStatusBlock,
483 IOCTL_AFD_SEND_DATAGRAM,
484 &SendInfo,
485 sizeof(SendInfo),
486 NULL,
487 0);
488
489 /* Increase the pending APC Count if we're using an APC */
490 if (!NT_ERROR(Status) && ApcFunction)
491 {
492 ThreadData->PendingAPCs++;
493 InterlockedIncrement(&SockProcessPendingAPCCount);
494 }
495
496 /* Wait for completition if not overlapped */
497 if ((Status == STATUS_PENDING) && !(lpOverlapped))
498 {
499 /* Wait for completion */
500 ReturnValue = SockWaitForSingleObject(Event,
501 Handle,
502 MAYBE_BLOCKING_HOOK,
503 SEND_TIMEOUT);
504
505 /* Check if the wait was successful */
506 if (ReturnValue)
507 {
508 /* Get new status */
509 Status = IoStatusBlock->Status;
510 }
511 else
512 {
513 /* Cancel the I/O */
514 SockCancelIo(Handle);
515 Status = STATUS_IO_TIMEOUT;
516 }
517 }
518
519 /* Check status */
520 switch (Status)
521 {
522 /* Success */
523 case STATUS_SUCCESS:
524 break;
525
526 /* Pending I/O */
527 case STATUS_PENDING:
528 ErrorCode = WSA_IO_PENDING;
529 goto error;
530
531 /* Other NT Error */
532 default:
533 if (!NT_SUCCESS(Status))
534 {
535 /* Fail */
536 ErrorCode = NtStatusToSocketError(Status);
537 goto error;
538 }
539 break;
540 }
541
542 /* Return the number of bytes sent */
543 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
544
545 error:
546
547 /* Check if we have a socket */
548 if (Socket)
549 {
550 /* Check if async select was active and this blocked */
551 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
552 {
553 /* Lock it */
554 EnterCriticalSection(&Socket->Lock);
555
556 /* Re-enable the regular write event */
557 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
558
559 /* Unlock socket */
560 LeaveCriticalSection(&Socket->Lock);
561 }
562
563 /* Dereference socket */
564 SockDereferenceSocket(Socket);
565 }
566
567 /* Check if we should free the TDI Address */
568 if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer))
569 {
570 /* Free it from the heap */
571 RtlFreeHeap(SockPrivateHeap, 0, TdiAddress);
572 }
573
574 /* Check for error */
575 if (ErrorCode != NO_ERROR)
576 {
577 /* Fail */
578 *lpErrno = ErrorCode;
579 return SOCKET_ERROR;
580 }
581
582 /* Return success */
583 return NO_ERROR;
584 }
585
586 /*
587 * COPYRIGHT: See COPYING in the top level directory
588 * PROJECT: ReactOS Winsock 2 SPI
589 * FILE: lib/mswsock/lib/init.c
590 * PURPOSE: DLL Initialization
591 */
592
593 /* INCLUDES ******************************************************************/
594 #include "msafd.h"
595
596 /* DATA **********************************************************************/
597
598 /* FUNCTIONS *****************************************************************/
599
600 INT
601 WSPAPI
602 WSPSend(SOCKET Handle,
603 LPWSABUF lpBuffers,
604 DWORD dwBufferCount,
605 LPDWORD lpNumberOfBytesSent,
606 DWORD iFlags,
607 LPWSAOVERLAPPED lpOverlapped,
608 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
609 LPWSATHREADID lpThreadId,
610 LPINT lpErrno)
611 {
612 PIO_STATUS_BLOCK IoStatusBlock;
613 IO_STATUS_BLOCK DummyIoStatusBlock;
614 AFD_SEND_INFO SendInfo;
615 NTSTATUS Status;
616 PVOID APCContext;
617 PVOID ApcFunction;
618 HANDLE Event;
619 PWINSOCK_TEB_DATA ThreadData;
620 PSOCKET_INFORMATION Socket;
621 INT ErrorCode;
622 BOOLEAN ReturnValue;
623
624 /* Enter prolog */
625 ErrorCode = SockEnterApiFast(&ThreadData);
626 if (ErrorCode != NO_ERROR)
627 {
628 /* Fail */
629 *lpErrno = ErrorCode;
630 return SOCKET_ERROR;
631 }
632
633 /* Set up the Receive Structure */
634 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
635 SendInfo.BufferCount = dwBufferCount;
636 SendInfo.TdiFlags = 0;
637 SendInfo.AfdFlags = 0;
638
639 /* Set the TDI Flags */
640 if (iFlags)
641 {
642 /* Check for valid flags */
643 if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL)))
644 {
645 /* Fail */
646 ErrorCode = WSAEOPNOTSUPP;
647 goto error;
648 }
649
650 /* Check if OOB is being used */
651 if (iFlags & MSG_OOB)
652 {
653 /* Use Expedited Send for OOB */
654 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
655 }
656
657 /* Use Partial Send if enabled */
658 if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
659 }
660
661 /* Verifiy if we should use APC */
662 if (!lpOverlapped)
663 {
664 /* Not using Overlapped structure, so use normal blocking on event */
665 APCContext = NULL;
666 ApcFunction = NULL;
667 Event = ThreadData->EventHandle;
668 IoStatusBlock = &DummyIoStatusBlock;
669 }
670 else
671 {
672 /* Using apc, check if we have a completion routine */
673 if (!lpCompletionRoutine)
674 {
675 /* No need for APC */
676 APCContext = lpOverlapped;
677 ApcFunction = NULL;
678 Event = lpOverlapped->hEvent;
679 }
680 else
681 {
682 /* Use APC */
683 ApcFunction = SockIoCompletion;
684 APCContext = lpCompletionRoutine;
685 Event = NULL;
686
687 /* Skip Fast I/O */
688 SendInfo.AfdFlags = AFD_SKIP_FIO;
689 }
690
691 /* Use the overlapped's structure buffer for the I/O Status Block */
692 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
693
694 /* Make this an overlapped I/O in AFD */
695 SendInfo.AfdFlags |= AFD_OVERLAPPED;
696 }
697
698 /* Set is as Pending for now */
699 IoStatusBlock->Status = STATUS_PENDING;
700
701 /* Send IOCTL */
702 Status = NtDeviceIoControlFile((HANDLE)Handle,
703 Event,
704 ApcFunction,
705 APCContext,
706 IoStatusBlock,
707 IOCTL_AFD_SEND,
708 &SendInfo,
709 sizeof(SendInfo),
710 NULL,
711 0);
712
713 /* Increase the pending APC Count if we're using an APC */
714 if (!NT_ERROR(Status) && ApcFunction)
715 {
716 ThreadData->PendingAPCs++;
717 InterlockedIncrement(&SockProcessPendingAPCCount);
718 }
719
720 /* Wait for completition if not overlapped */
721 if ((Status == STATUS_PENDING) && !(lpOverlapped))
722 {
723 /* Wait for completion */
724 ReturnValue = SockWaitForSingleObject(Event,
725 Handle,
726 MAYBE_BLOCKING_HOOK,
727 SEND_TIMEOUT);
728
729 /* Check if the wait was successful */
730 if (ReturnValue)
731 {
732 /* Get new status */
733 Status = IoStatusBlock->Status;
734 }
735 else
736 {
737 /* Cancel the I/O */
738 SockCancelIo(Handle);
739 Status = STATUS_IO_TIMEOUT;
740 }
741 }
742
743 /* Check status */
744 switch (Status)
745 {
746 /* Success */
747 case STATUS_SUCCESS:
748 break;
749
750 /* Pending I/O */
751 case STATUS_PENDING:
752 ErrorCode = WSA_IO_PENDING;
753 goto error;
754
755 /* Other NT Error */
756 default:
757 if (!NT_SUCCESS(Status))
758 {
759 /* Fail */
760 ErrorCode = NtStatusToSocketError(Status);
761 goto error;
762 }
763 break;
764 }
765
766 /* Return the number of bytes sent */
767 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
768
769 error:
770
771 /* Check if async select was active and this blocked */
772 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
773 {
774 /* Get the socket */
775 Socket = SockFindAndReferenceSocket(Handle, TRUE);
776 if (Socket)
777 {
778 /* Lock it */
779 EnterCriticalSection(&Socket->Lock);
780
781 /* Re-enable the regular write event */
782 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
783
784 /* Unlock and dereference socket */
785 LeaveCriticalSection(&Socket->Lock);
786 SockDereferenceSocket(Socket);
787 }
788 }
789
790 /* Check for error */
791 if (ErrorCode != NO_ERROR)
792 {
793 /* Fail */
794 *lpErrno = ErrorCode;
795 return SOCKET_ERROR;
796 }
797
798 /* Return success */
799 return NO_ERROR;
800 }
801
802 INT
803 WSPAPI
804 WSPSendTo(SOCKET Handle,
805 LPWSABUF lpBuffers,
806 DWORD dwBufferCount,
807 LPDWORD lpNumberOfBytesSent,
808 DWORD iFlags,
809 const struct sockaddr *SocketAddress,
810 INT SocketAddressLength,
811 LPWSAOVERLAPPED lpOverlapped,
812 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
813 LPWSATHREADID lpThreadId,
814 LPINT lpErrno)
815 {
816 PIO_STATUS_BLOCK IoStatusBlock;
817 IO_STATUS_BLOCK DummyIoStatusBlock;
818 AFD_SEND_INFO_UDP SendInfo;
819 NTSTATUS Status;
820 PVOID APCContext;
821 PVOID ApcFunction;
822 HANDLE Event;
823 PWINSOCK_TEB_DATA ThreadData;
824 PSOCKET_INFORMATION Socket;
825 INT ErrorCode;
826 INT ReturnValue;
827 CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) +
828 MAX_TDI_ADDRESS_LENGTH];
829 PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer;
830 ULONG TdiAddressSize;
831 INT SockaddrLength;
832 PSOCKADDR Sockaddr;
833 SOCKADDR_INFO SocketInfo;
834
835 /* Enter prolog */
836 ErrorCode = SockEnterApiFast(&ThreadData);
837 if (ErrorCode != NO_ERROR)
838 {
839 /* Fail */
840 *lpErrno = ErrorCode;
841 return SOCKET_ERROR;
842 }
843
844 /* Get the socket structure */
845 Socket = SockFindAndReferenceSocket(Handle, TRUE);
846 if (!Socket)
847 {
848 /* Fail */
849 ErrorCode = WSAENOTSOCK;
850 goto error;
851 }
852
853 /*
854 * Check if this isn't a datagram socket or if it's a connected socket
855 * without an address
856 */
857 if (!MSAFD_IS_DGRAM_SOCK(Socket) ||
858 ((Socket->SharedData.State == SocketConnected) &&
859 (!SocketAddress || !SocketAddressLength)))
860 {
861 /* Call WSPSend instead */
862 SockDereferenceSocket(Socket);
863 return WSPSend(Handle,
864 lpBuffers,
865 dwBufferCount,
866 lpNumberOfBytesSent,
867 iFlags,
868 lpOverlapped,
869 lpCompletionRoutine,
870 lpThreadId,
871 lpErrno);
872 }
873
874 /* If the socket isn't connected, we need an address*/
875 if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress))
876 {
877 /* Fail */
878 ErrorCode = WSAENOTCONN;
879 goto error;
880 }
881
882 /* Validate length */
883 if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength)
884 {
885 /* Fail */
886 ErrorCode = WSAEFAULT;
887 goto error;
888 }
889
890 /* Verify flags */
891 if (iFlags & ~MSG_DONTROUTE)
892 {
893 /* Fail */
894 ErrorCode = WSAEOPNOTSUPP;
895 goto error;
896 }
897
898 /* Make sure send shutdown isn't active */
899 if (Socket->SharedData.SendShutdown)
900 {
901 /* Fail */
902 ErrorCode = WSAESHUTDOWN;
903 goto error;
904 }
905
906 /* Make sure address families match */
907 if (Socket->SharedData.AddressFamily != SocketAddress->sa_family)
908 {
909 /* Fail */
910 ErrorCode = WSAEOPNOTSUPP;
911 goto error;
912 }
913
914 /* Check if broadcast is enabled */
915 if (!Socket->SharedData.Broadcast)
916 {
917 /* The caller might want to enable it; get the Sockaddr type */
918 ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress,
919 SocketAddressLength,
920 &SocketInfo);
921 if (ErrorCode != NO_ERROR) goto error;
922
923 /* Check if this is a broadcast attempt */
924 if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast)
925 {
926 /* The socket won't allow it */
927 ErrorCode = WSAEACCES;
928 goto error;
929 }
930 }
931
932 /* Check if this socket isn't bound yet */
933 if (Socket->SharedData.State == SocketOpen)
934 {
935 /* Check if we can request the wildcard address */
936 if (Socket->HelperData->WSHGetWildcardSockaddr)
937 {
938 /* Allocate a new Sockaddr */
939 SockaddrLength = Socket->HelperData->MaxWSAddressLength;
940 Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength);
941 if (!Sockaddr)
942 {
943 /* Fail */
944 ErrorCode = WSAENOBUFS;
945 goto error;
946 }
947
948 /* Get the wildcard sockaddr */
949 ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
950 Sockaddr,
951 &SockaddrLength);
952 if (ErrorCode != NO_ERROR)
953 {
954 /* Free memory and fail */
955 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
956 goto error;
957 }
958
959 /* Lock the socket */
960 EnterCriticalSection(&Socket->Lock);
961
962 /* Make sure it's still unbound */
963 if (Socket->SharedData.State == SocketOpen)
964 {
965 /* Bind it */
966 ReturnValue = WSPBind(Handle,
967 Sockaddr,
968 SockaddrLength,
969 &ErrorCode);
970 }
971 else
972 {
973 /* It's bound now, fake success */
974 ReturnValue = NO_ERROR;
975 }
976
977 /* Release the lock and free memory */
978 LeaveCriticalSection(&Socket->Lock);
979 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
980
981 /* Check if we failed */
982 if (ReturnValue == SOCKET_ERROR) goto error;
983 }
984 else
985 {
986 /* Unbound socket, but can't get the wildcard. Fail */
987 ErrorCode = WSAEINVAL;
988 goto error;
989 }
990 }
991
992 /* Check how long the TDI Address is */
993 TdiAddressSize = Socket->HelperData->MaxTDIAddressLength;
994
995 /* See if it can fit in the stack */
996 if (TdiAddressSize > sizeof(AddressBuffer))
997 {
998 /* Allocate from heap */
999 TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize);
1000 if (!TdiAddress)
1001 {
1002 /* Fail */
1003 ErrorCode = WSAENOBUFS;
1004 goto error;
1005 }
1006 }
1007
1008 /* Build the TDI Address */
1009 ErrorCode = SockBuildTdiAddress(TdiAddress,
1010 (PSOCKADDR)SocketAddress,
1011 min(SocketAddressLength,
1012 Socket->HelperData->MaxWSAddressLength));
1013 if (ErrorCode != NO_ERROR) goto error;
1014
1015 /* Set up the Send Structure */
1016 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
1017 SendInfo.BufferCount = dwBufferCount;
1018 SendInfo.AfdFlags = 0;
1019 SendInfo.TdiConnection.RemoteAddress = TdiAddress;
1020 SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize;
1021
1022 /* Verifiy if we should use APC */
1023 if (!lpOverlapped)
1024 {
1025 /* Not using Overlapped structure, so use normal blocking on event */
1026 APCContext = NULL;
1027 ApcFunction = NULL;
1028 Event = ThreadData->EventHandle;
1029 IoStatusBlock = &DummyIoStatusBlock;
1030 }
1031 else
1032 {
1033 /* Using apc, check if we have a completion routine */
1034 if (!lpCompletionRoutine)
1035 {
1036 /* No need for APC */
1037 APCContext = lpOverlapped;
1038 ApcFunction = NULL;
1039 Event = lpOverlapped->hEvent;
1040 }
1041 else
1042 {
1043 /* Use APC */
1044 ApcFunction = SockIoCompletion;
1045 APCContext = lpCompletionRoutine;
1046 Event = NULL;
1047
1048 /* Skip Fast I/O */
1049 SendInfo.AfdFlags = AFD_SKIP_FIO;
1050 }
1051
1052 /* Use the overlapped's structure buffer for the I/O Status Block */
1053 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
1054
1055 /* Make this an overlapped I/O in AFD */
1056 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1057 }
1058
1059 /* Set is as Pending for now */
1060 IoStatusBlock->Status = STATUS_PENDING;
1061
1062 /* Send IOCTL */
1063 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1064 Event,
1065 ApcFunction,
1066 APCContext,
1067 IoStatusBlock,
1068 IOCTL_AFD_SEND_DATAGRAM,
1069 &SendInfo,
1070 sizeof(SendInfo),
1071 NULL,
1072 0);
1073
1074 /* Increase the pending APC Count if we're using an APC */
1075 if (!NT_ERROR(Status) && ApcFunction)
1076 {
1077 ThreadData->PendingAPCs++;
1078 InterlockedIncrement(&SockProcessPendingAPCCount);
1079 }
1080
1081 /* Wait for completition if not overlapped */
1082 if ((Status == STATUS_PENDING) && !(lpOverlapped))
1083 {
1084 /* Wait for completion */
1085 ReturnValue = SockWaitForSingleObject(Event,
1086 Handle,
1087 MAYBE_BLOCKING_HOOK,
1088 SEND_TIMEOUT);
1089
1090 /* Check if the wait was successful */
1091 if (ReturnValue)
1092 {
1093 /* Get new status */
1094 Status = IoStatusBlock->Status;
1095 }
1096 else
1097 {
1098 /* Cancel the I/O */
1099 SockCancelIo(Handle);
1100 Status = STATUS_IO_TIMEOUT;
1101 }
1102 }
1103
1104 /* Check status */
1105 switch (Status)
1106 {
1107 /* Success */
1108 case STATUS_SUCCESS:
1109 break;
1110
1111 /* Pending I/O */
1112 case STATUS_PENDING:
1113 ErrorCode = WSA_IO_PENDING;
1114 goto error;
1115
1116 /* Other NT Error */
1117 default:
1118 if (!NT_SUCCESS(Status))
1119 {
1120 /* Fail */
1121 ErrorCode = NtStatusToSocketError(Status);
1122 goto error;
1123 }
1124 break;
1125 }
1126
1127 /* Return the number of bytes sent */
1128 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
1129
1130 error:
1131
1132 /* Check if we have a socket */
1133 if (Socket)
1134 {
1135 /* Check if async select was active and this blocked */
1136 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
1137 {
1138 /* Lock it */
1139 EnterCriticalSection(&Socket->Lock);
1140
1141 /* Re-enable the regular write event */
1142 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1143
1144 /* Unlock socket */
1145 LeaveCriticalSection(&Socket->Lock);
1146 }
1147
1148 /* Dereference socket */
1149 SockDereferenceSocket(Socket);
1150 }
1151
1152 /* Check if we should free the TDI Address */
1153 if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer))
1154 {
1155 /* Free it from the heap */
1156 RtlFreeHeap(SockPrivateHeap, 0, TdiAddress);
1157 }
1158
1159 /* Check for error */
1160 if (ErrorCode != NO_ERROR)
1161 {
1162 /* Fail */
1163 *lpErrno = ErrorCode;
1164 return SOCKET_ERROR;
1165 }
1166
1167 /* Return success */
1168 return NO_ERROR;
1169 }
1170
1171 /*
1172 * COPYRIGHT: See COPYING in the top level directory
1173 * PROJECT: ReactOS Winsock 2 SPI
1174 * FILE: lib/mswsock/lib/init.c
1175 * PURPOSE: DLL Initialization
1176 */
1177
1178 /* INCLUDES ******************************************************************/
1179 #include "msafd.h"
1180
1181 /* DATA **********************************************************************/
1182
1183 /* FUNCTIONS *****************************************************************/
1184
1185 INT
1186 WSPAPI
1187 WSPSend(SOCKET Handle,
1188 LPWSABUF lpBuffers,
1189 DWORD dwBufferCount,
1190 LPDWORD lpNumberOfBytesSent,
1191 DWORD iFlags,
1192 LPWSAOVERLAPPED lpOverlapped,
1193 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1194 LPWSATHREADID lpThreadId,
1195 LPINT lpErrno)
1196 {
1197 PIO_STATUS_BLOCK IoStatusBlock;
1198 IO_STATUS_BLOCK DummyIoStatusBlock;
1199 AFD_SEND_INFO SendInfo;
1200 NTSTATUS Status;
1201 PVOID APCContext;
1202 PVOID ApcFunction;
1203 HANDLE Event;
1204 PWINSOCK_TEB_DATA ThreadData;
1205 PSOCKET_INFORMATION Socket;
1206 INT ErrorCode;
1207 BOOLEAN ReturnValue;
1208
1209 /* Enter prolog */
1210 ErrorCode = SockEnterApiFast(&ThreadData);
1211 if (ErrorCode != NO_ERROR)
1212 {
1213 /* Fail */
1214 *lpErrno = ErrorCode;
1215 return SOCKET_ERROR;
1216 }
1217
1218 /* Set up the Receive Structure */
1219 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
1220 SendInfo.BufferCount = dwBufferCount;
1221 SendInfo.TdiFlags = 0;
1222 SendInfo.AfdFlags = 0;
1223
1224 /* Set the TDI Flags */
1225 if (iFlags)
1226 {
1227 /* Check for valid flags */
1228 if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL)))
1229 {
1230 /* Fail */
1231 ErrorCode = WSAEOPNOTSUPP;
1232 goto error;
1233 }
1234
1235 /* Check if OOB is being used */
1236 if (iFlags & MSG_OOB)
1237 {
1238 /* Use Expedited Send for OOB */
1239 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
1240 }
1241
1242 /* Use Partial Send if enabled */
1243 if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
1244 }
1245
1246 /* Verifiy if we should use APC */
1247 if (!lpOverlapped)
1248 {
1249 /* Not using Overlapped structure, so use normal blocking on event */
1250 APCContext = NULL;
1251 ApcFunction = NULL;
1252 Event = ThreadData->EventHandle;
1253 IoStatusBlock = &DummyIoStatusBlock;
1254 }
1255 else
1256 {
1257 /* Using apc, check if we have a completion routine */
1258 if (!lpCompletionRoutine)
1259 {
1260 /* No need for APC */
1261 APCContext = lpOverlapped;
1262 ApcFunction = NULL;
1263 Event = lpOverlapped->hEvent;
1264 }
1265 else
1266 {
1267 /* Use APC */
1268 ApcFunction = SockIoCompletion;
1269 APCContext = lpCompletionRoutine;
1270 Event = NULL;
1271
1272 /* Skip Fast I/O */
1273 SendInfo.AfdFlags = AFD_SKIP_FIO;
1274 }
1275
1276 /* Use the overlapped's structure buffer for the I/O Status Block */
1277 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
1278
1279 /* Make this an overlapped I/O in AFD */
1280 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1281 }
1282
1283 /* Set is as Pending for now */
1284 IoStatusBlock->Status = STATUS_PENDING;
1285
1286 /* Send IOCTL */
1287 Status = NtDeviceIoControlFile((HANDLE)Handle,
1288 Event,
1289 ApcFunction,
1290 APCContext,
1291 IoStatusBlock,
1292 IOCTL_AFD_SEND,
1293 &SendInfo,
1294 sizeof(SendInfo),
1295 NULL,
1296 0);
1297
1298 /* Increase the pending APC Count if we're using an APC */
1299 if (!NT_ERROR(Status) && ApcFunction)
1300 {
1301 ThreadData->PendingAPCs++;
1302 InterlockedIncrement(&SockProcessPendingAPCCount);
1303 }
1304
1305 /* Wait for completition if not overlapped */
1306 if ((Status == STATUS_PENDING) && !(lpOverlapped))
1307 {
1308 /* Wait for completion */
1309 ReturnValue = SockWaitForSingleObject(Event,
1310 Handle,
1311 MAYBE_BLOCKING_HOOK,
1312 SEND_TIMEOUT);
1313
1314 /* Check if the wait was successful */
1315 if (ReturnValue)
1316 {
1317 /* Get new status */
1318 Status = IoStatusBlock->Status;
1319 }
1320 else
1321 {
1322 /* Cancel the I/O */
1323 SockCancelIo(Handle);
1324 Status = STATUS_IO_TIMEOUT;
1325 }
1326 }
1327
1328 /* Check status */
1329 switch (Status)
1330 {
1331 /* Success */
1332 case STATUS_SUCCESS:
1333 break;
1334
1335 /* Pending I/O */
1336 case STATUS_PENDING:
1337 ErrorCode = WSA_IO_PENDING;
1338 goto error;
1339
1340 /* Other NT Error */
1341 default:
1342 if (!NT_SUCCESS(Status))
1343 {
1344 /* Fail */
1345 ErrorCode = NtStatusToSocketError(Status);
1346 goto error;
1347 }
1348 break;
1349 }
1350
1351 /* Return the number of bytes sent */
1352 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
1353
1354 error:
1355
1356 /* Check if async select was active and this blocked */
1357 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
1358 {
1359 /* Get the socket */
1360 Socket = SockFindAndReferenceSocket(Handle, TRUE);
1361 if (Socket)
1362 {
1363 /* Lock it */
1364 EnterCriticalSection(&Socket->Lock);
1365
1366 /* Re-enable the regular write event */
1367 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1368
1369 /* Unlock and dereference socket */
1370 LeaveCriticalSection(&Socket->Lock);
1371 SockDereferenceSocket(Socket);
1372 }
1373 }
1374
1375 /* Check for error */
1376 if (ErrorCode != NO_ERROR)
1377 {
1378 /* Fail */
1379 *lpErrno = ErrorCode;
1380 return SOCKET_ERROR;
1381 }
1382
1383 /* Return success */
1384 return NO_ERROR;
1385 }
1386
1387 INT
1388 WSPAPI
1389 WSPSendTo(SOCKET Handle,
1390 LPWSABUF lpBuffers,
1391 DWORD dwBufferCount,
1392 LPDWORD lpNumberOfBytesSent,
1393 DWORD iFlags,
1394 const struct sockaddr *SocketAddress,
1395 INT SocketAddressLength,
1396 LPWSAOVERLAPPED lpOverlapped,
1397 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1398 LPWSATHREADID lpThreadId,
1399 LPINT lpErrno)
1400 {
1401 PIO_STATUS_BLOCK IoStatusBlock;
1402 IO_STATUS_BLOCK DummyIoStatusBlock;
1403 AFD_SEND_INFO_UDP SendInfo;
1404 NTSTATUS Status;
1405 PVOID APCContext;
1406 PVOID ApcFunction;
1407 HANDLE Event;
1408 PWINSOCK_TEB_DATA ThreadData;
1409 PSOCKET_INFORMATION Socket;
1410 INT ErrorCode;
1411 INT ReturnValue;
1412 CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) +
1413 MAX_TDI_ADDRESS_LENGTH];
1414 PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer;
1415 ULONG TdiAddressSize;
1416 INT SockaddrLength;
1417 PSOCKADDR Sockaddr;
1418 SOCKADDR_INFO SocketInfo;
1419
1420 /* Enter prolog */
1421 ErrorCode = SockEnterApiFast(&ThreadData);
1422 if (ErrorCode != NO_ERROR)
1423 {
1424 /* Fail */
1425 *lpErrno = ErrorCode;
1426 return SOCKET_ERROR;
1427 }
1428
1429 /* Get the socket structure */
1430 Socket = SockFindAndReferenceSocket(Handle, TRUE);
1431 if (!Socket)
1432 {
1433 /* Fail */
1434 ErrorCode = WSAENOTSOCK;
1435 goto error;
1436 }
1437
1438 /*
1439 * Check if this isn't a datagram socket or if it's a connected socket
1440 * without an address
1441 */
1442 if (!MSAFD_IS_DGRAM_SOCK(Socket) ||
1443 ((Socket->SharedData.State == SocketConnected) &&
1444 (!SocketAddress || !SocketAddressLength)))
1445 {
1446 /* Call WSPSend instead */
1447 SockDereferenceSocket(Socket);
1448 return WSPSend(Handle,
1449 lpBuffers,
1450 dwBufferCount,
1451 lpNumberOfBytesSent,
1452 iFlags,
1453 lpOverlapped,
1454 lpCompletionRoutine,
1455 lpThreadId,
1456 lpErrno);
1457 }
1458
1459 /* If the socket isn't connected, we need an address*/
1460 if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress))
1461 {
1462 /* Fail */
1463 ErrorCode = WSAENOTCONN;
1464 goto error;
1465 }
1466
1467 /* Validate length */
1468 if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength)
1469 {
1470 /* Fail */
1471 ErrorCode = WSAEFAULT;
1472 goto error;
1473 }
1474
1475 /* Verify flags */
1476 if (iFlags & ~MSG_DONTROUTE)
1477 {
1478 /* Fail */
1479 ErrorCode = WSAEOPNOTSUPP;
1480 goto error;
1481 }
1482
1483 /* Make sure send shutdown isn't active */
1484 if (Socket->SharedData.SendShutdown)
1485 {
1486 /* Fail */
1487 ErrorCode = WSAESHUTDOWN;
1488 goto error;
1489 }
1490
1491 /* Make sure address families match */
1492 if (Socket->SharedData.AddressFamily != SocketAddress->sa_family)
1493 {
1494 /* Fail */
1495 ErrorCode = WSAEOPNOTSUPP;
1496 goto error;
1497 }
1498
1499 /* Check if broadcast is enabled */
1500 if (!Socket->SharedData.Broadcast)
1501 {
1502 /* The caller might want to enable it; get the Sockaddr type */
1503 ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress,
1504 SocketAddressLength,
1505 &SocketInfo);
1506 if (ErrorCode != NO_ERROR) goto error;
1507
1508 /* Check if this is a broadcast attempt */
1509 if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast)
1510 {
1511 /* The socket won't allow it */
1512 ErrorCode = WSAEACCES;
1513 goto error;
1514 }
1515 }
1516
1517 /* Check if this socket isn't bound yet */
1518 if (Socket->SharedData.State == SocketOpen)
1519 {
1520 /* Check if we can request the wildcard address */
1521 if (Socket->HelperData->WSHGetWildcardSockaddr)
1522 {
1523 /* Allocate a new Sockaddr */
1524 SockaddrLength = Socket->HelperData->MaxWSAddressLength;
1525 Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength);
1526 if (!Sockaddr)
1527 {
1528 /* Fail */
1529 ErrorCode = WSAENOBUFS;
1530 goto error;
1531 }
1532
1533 /* Get the wildcard sockaddr */
1534 ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
1535 Sockaddr,
1536 &SockaddrLength);
1537 if (ErrorCode != NO_ERROR)
1538 {
1539 /* Free memory and fail */
1540 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
1541 goto error;
1542 }
1543
1544 /* Lock the socket */
1545 EnterCriticalSection(&Socket->Lock);
1546
1547 /* Make sure it's still unbound */
1548 if (Socket->SharedData.State == SocketOpen)
1549 {
1550 /* Bind it */
1551 ReturnValue = WSPBind(Handle,
1552 Sockaddr,
1553 SockaddrLength,
1554 &ErrorCode);
1555 }
1556 else
1557 {
1558 /* It's bound now, fake success */
1559 ReturnValue = NO_ERROR;
1560 }
1561
1562 /* Release the lock and free memory */
1563 LeaveCriticalSection(&Socket->Lock);
1564 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
1565
1566 /* Check if we failed */
1567 if (ReturnValue == SOCKET_ERROR) goto error;
1568 }
1569 else
1570 {
1571 /* Unbound socket, but can't get the wildcard. Fail */
1572 ErrorCode = WSAEINVAL;
1573 goto error;
1574 }
1575 }
1576
1577 /* Check how long the TDI Address is */
1578 TdiAddressSize = Socket->HelperData->MaxTDIAddressLength;
1579
1580 /* See if it can fit in the stack */
1581 if (TdiAddressSize > sizeof(AddressBuffer))
1582 {
1583 /* Allocate from heap */
1584 TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize);
1585 if (!TdiAddress)
1586 {
1587 /* Fail */
1588 ErrorCode = WSAENOBUFS;
1589 goto error;
1590 }
1591 }
1592
1593 /* Build the TDI Address */
1594 ErrorCode = SockBuildTdiAddress(TdiAddress,
1595 (PSOCKADDR)SocketAddress,
1596 min(SocketAddressLength,
1597 Socket->HelperData->MaxWSAddressLength));
1598 if (ErrorCode != NO_ERROR) goto error;
1599
1600 /* Set up the Send Structure */
1601 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
1602 SendInfo.BufferCount = dwBufferCount;
1603 SendInfo.AfdFlags = 0;
1604 SendInfo.TdiConnection.RemoteAddress = TdiAddress;
1605 SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize;
1606
1607 /* Verifiy if we should use APC */
1608 if (!lpOverlapped)
1609 {
1610 /* Not using Overlapped structure, so use normal blocking on event */
1611 APCContext = NULL;
1612 ApcFunction = NULL;
1613 Event = ThreadData->EventHandle;
1614 IoStatusBlock = &DummyIoStatusBlock;
1615 }
1616 else
1617 {
1618 /* Using apc, check if we have a completion routine */
1619 if (!lpCompletionRoutine)
1620 {
1621 /* No need for APC */
1622 APCContext = lpOverlapped;
1623 ApcFunction = NULL;
1624 Event = lpOverlapped->hEvent;
1625 }
1626 else
1627 {
1628 /* Use APC */
1629 ApcFunction = SockIoCompletion;
1630 APCContext = lpCompletionRoutine;
1631 Event = NULL;
1632
1633 /* Skip Fast I/O */
1634 SendInfo.AfdFlags = AFD_SKIP_FIO;
1635 }
1636
1637 /* Use the overlapped's structure buffer for the I/O Status Block */
1638 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
1639
1640 /* Make this an overlapped I/O in AFD */
1641 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1642 }
1643
1644 /* Set is as Pending for now */
1645 IoStatusBlock->Status = STATUS_PENDING;
1646
1647 /* Send IOCTL */
1648 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1649 Event,
1650 ApcFunction,
1651 APCContext,
1652 IoStatusBlock,
1653 IOCTL_AFD_SEND_DATAGRAM,
1654 &SendInfo,
1655 sizeof(SendInfo),
1656 NULL,
1657 0);
1658
1659 /* Increase the pending APC Count if we're using an APC */
1660 if (!NT_ERROR(Status) && ApcFunction)
1661 {
1662 ThreadData->PendingAPCs++;
1663 InterlockedIncrement(&SockProcessPendingAPCCount);
1664 }
1665
1666 /* Wait for completition if not overlapped */
1667 if ((Status == STATUS_PENDING) && !(lpOverlapped))
1668 {
1669 /* Wait for completion */
1670 ReturnValue = SockWaitForSingleObject(Event,
1671 Handle,
1672 MAYBE_BLOCKING_HOOK,
1673 SEND_TIMEOUT);
1674
1675 /* Check if the wait was successful */
1676 if (ReturnValue)
1677 {
1678 /* Get new status */
1679 Status = IoStatusBlock->Status;
1680 }
1681 else
1682 {
1683 /* Cancel the I/O */
1684 SockCancelIo(Handle);
1685 Status = STATUS_IO_TIMEOUT;
1686 }
1687 }
1688
1689 /* Check status */
1690 switch (Status)
1691 {
1692 /* Success */
1693 case STATUS_SUCCESS:
1694 break;
1695
1696 /* Pending I/O */
1697 case STATUS_PENDING:
1698 ErrorCode = WSA_IO_PENDING;
1699 goto error;
1700
1701 /* Other NT Error */
1702 default:
1703 if (!NT_SUCCESS(Status))
1704 {
1705 /* Fail */
1706 ErrorCode = NtStatusToSocketError(Status);
1707 goto error;
1708 }
1709 break;
1710 }
1711
1712 /* Return the number of bytes sent */
1713 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
1714
1715 error:
1716
1717 /* Check if we have a socket */
1718 if (Socket)
1719 {
1720 /* Check if async select was active and this blocked */
1721 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
1722 {
1723 /* Lock it */
1724 EnterCriticalSection(&Socket->Lock);
1725
1726 /* Re-enable the regular write event */
1727 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1728
1729 /* Unlock socket */
1730 LeaveCriticalSection(&Socket->Lock);
1731 }
1732
1733 /* Dereference socket */
1734 SockDereferenceSocket(Socket);
1735 }
1736
1737 /* Check if we should free the TDI Address */
1738 if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer))
1739 {
1740 /* Free it from the heap */
1741 RtlFreeHeap(SockPrivateHeap, 0, TdiAddress);
1742 }
1743
1744 /* Check for error */
1745 if (ErrorCode != NO_ERROR)
1746 {
1747 /* Fail */
1748 *lpErrno = ErrorCode;
1749 return SOCKET_ERROR;
1750 }
1751
1752 /* Return success */
1753 return NO_ERROR;
1754 }
1755
1756 /*
1757 * COPYRIGHT: See COPYING in the top level directory
1758 * PROJECT: ReactOS Winsock 2 SPI
1759 * FILE: lib/mswsock/lib/init.c
1760 * PURPOSE: DLL Initialization
1761 */
1762
1763 /* INCLUDES ******************************************************************/
1764 #include "msafd.h"
1765
1766 /* DATA **********************************************************************/
1767
1768 /* FUNCTIONS *****************************************************************/
1769
1770 INT
1771 WSPAPI
1772 WSPSend(SOCKET Handle,
1773 LPWSABUF lpBuffers,
1774 DWORD dwBufferCount,
1775 LPDWORD lpNumberOfBytesSent,
1776 DWORD iFlags,
1777 LPWSAOVERLAPPED lpOverlapped,
1778 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1779 LPWSATHREADID lpThreadId,
1780 LPINT lpErrno)
1781 {
1782 PIO_STATUS_BLOCK IoStatusBlock;
1783 IO_STATUS_BLOCK DummyIoStatusBlock;
1784 AFD_SEND_INFO SendInfo;
1785 NTSTATUS Status;
1786 PVOID APCContext;
1787 PVOID ApcFunction;
1788 HANDLE Event;
1789 PWINSOCK_TEB_DATA ThreadData;
1790 PSOCKET_INFORMATION Socket;
1791 INT ErrorCode;
1792 BOOLEAN ReturnValue;
1793
1794 /* Enter prolog */
1795 ErrorCode = SockEnterApiFast(&ThreadData);
1796 if (ErrorCode != NO_ERROR)
1797 {
1798 /* Fail */
1799 *lpErrno = ErrorCode;
1800 return SOCKET_ERROR;
1801 }
1802
1803 /* Set up the Receive Structure */
1804 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
1805 SendInfo.BufferCount = dwBufferCount;
1806 SendInfo.TdiFlags = 0;
1807 SendInfo.AfdFlags = 0;
1808
1809 /* Set the TDI Flags */
1810 if (iFlags)
1811 {
1812 /* Check for valid flags */
1813 if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL)))
1814 {
1815 /* Fail */
1816 ErrorCode = WSAEOPNOTSUPP;
1817 goto error;
1818 }
1819
1820 /* Check if OOB is being used */
1821 if (iFlags & MSG_OOB)
1822 {
1823 /* Use Expedited Send for OOB */
1824 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
1825 }
1826
1827 /* Use Partial Send if enabled */
1828 if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
1829 }
1830
1831 /* Verifiy if we should use APC */
1832 if (!lpOverlapped)
1833 {
1834 /* Not using Overlapped structure, so use normal blocking on event */
1835 APCContext = NULL;
1836 ApcFunction = NULL;
1837 Event = ThreadData->EventHandle;
1838 IoStatusBlock = &DummyIoStatusBlock;
1839 }
1840 else
1841 {
1842 /* Using apc, check if we have a completion routine */
1843 if (!lpCompletionRoutine)
1844 {
1845 /* No need for APC */
1846 APCContext = lpOverlapped;
1847 ApcFunction = NULL;
1848 Event = lpOverlapped->hEvent;
1849 }
1850 else
1851 {
1852 /* Use APC */
1853 ApcFunction = SockIoCompletion;
1854 APCContext = lpCompletionRoutine;
1855 Event = NULL;
1856
1857 /* Skip Fast I/O */
1858 SendInfo.AfdFlags = AFD_SKIP_FIO;
1859 }
1860
1861 /* Use the overlapped's structure buffer for the I/O Status Block */
1862 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
1863
1864 /* Make this an overlapped I/O in AFD */
1865 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1866 }
1867
1868 /* Set is as Pending for now */
1869 IoStatusBlock->Status = STATUS_PENDING;
1870
1871 /* Send IOCTL */
1872 Status = NtDeviceIoControlFile((HANDLE)Handle,
1873 Event,
1874 ApcFunction,
1875 APCContext,
1876 IoStatusBlock,
1877 IOCTL_AFD_SEND,
1878 &SendInfo,
1879 sizeof(SendInfo),
1880 NULL,
1881 0);
1882
1883 /* Increase the pending APC Count if we're using an APC */
1884 if (!NT_ERROR(Status) && ApcFunction)
1885 {
1886 ThreadData->PendingAPCs++;
1887 InterlockedIncrement(&SockProcessPendingAPCCount);
1888 }
1889
1890 /* Wait for completition if not overlapped */
1891 if ((Status == STATUS_PENDING) && !(lpOverlapped))
1892 {
1893 /* Wait for completion */
1894 ReturnValue = SockWaitForSingleObject(Event,
1895 Handle,
1896 MAYBE_BLOCKING_HOOK,
1897 SEND_TIMEOUT);
1898
1899 /* Check if the wait was successful */
1900 if (ReturnValue)
1901 {
1902 /* Get new status */
1903 Status = IoStatusBlock->Status;
1904 }
1905 else
1906 {
1907 /* Cancel the I/O */
1908 SockCancelIo(Handle);
1909 Status = STATUS_IO_TIMEOUT;
1910 }
1911 }
1912
1913 /* Check status */
1914 switch (Status)
1915 {
1916 /* Success */
1917 case STATUS_SUCCESS:
1918 break;
1919
1920 /* Pending I/O */
1921 case STATUS_PENDING:
1922 ErrorCode = WSA_IO_PENDING;
1923 goto error;
1924
1925 /* Other NT Error */
1926 default:
1927 if (!NT_SUCCESS(Status))
1928 {
1929 /* Fail */
1930 ErrorCode = NtStatusToSocketError(Status);
1931 goto error;
1932 }
1933 break;
1934 }
1935
1936 /* Return the number of bytes sent */
1937 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
1938
1939 error:
1940
1941 /* Check if async select was active and this blocked */
1942 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
1943 {
1944 /* Get the socket */
1945 Socket = SockFindAndReferenceSocket(Handle, TRUE);
1946 if (Socket)
1947 {
1948 /* Lock it */
1949 EnterCriticalSection(&Socket->Lock);
1950
1951 /* Re-enable the regular write event */
1952 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1953
1954 /* Unlock and dereference socket */
1955 LeaveCriticalSection(&Socket->Lock);
1956 SockDereferenceSocket(Socket);
1957 }
1958 }
1959
1960 /* Check for error */
1961 if (ErrorCode != NO_ERROR)
1962 {
1963 /* Fail */
1964 *lpErrno = ErrorCode;
1965 return SOCKET_ERROR;
1966 }
1967
1968 /* Return success */
1969 return NO_ERROR;
1970 }
1971
1972 INT
1973 WSPAPI
1974 WSPSendTo(SOCKET Handle,
1975 LPWSABUF lpBuffers,
1976 DWORD dwBufferCount,
1977 LPDWORD lpNumberOfBytesSent,
1978 DWORD iFlags,
1979 const struct sockaddr *SocketAddress,
1980 INT SocketAddressLength,
1981 LPWSAOVERLAPPED lpOverlapped,
1982 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1983 LPWSATHREADID lpThreadId,
1984 LPINT lpErrno)
1985 {
1986 PIO_STATUS_BLOCK IoStatusBlock;
1987 IO_STATUS_BLOCK DummyIoStatusBlock;
1988 AFD_SEND_INFO_UDP SendInfo;
1989 NTSTATUS Status;
1990 PVOID APCContext;
1991 PVOID ApcFunction;
1992 HANDLE Event;
1993 PWINSOCK_TEB_DATA ThreadData;
1994 PSOCKET_INFORMATION Socket;
1995 INT ErrorCode;
1996 INT ReturnValue;
1997 CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) +
1998 MAX_TDI_ADDRESS_LENGTH];
1999 PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer;
2000 ULONG TdiAddressSize;
2001 INT SockaddrLength;
2002 PSOCKADDR Sockaddr;
2003 SOCKADDR_INFO SocketInfo;
2004
2005 /* Enter prolog */
2006 ErrorCode = SockEnterApiFast(&ThreadData);
2007 if (ErrorCode != NO_ERROR)
2008 {
2009 /* Fail */
2010 *lpErrno = ErrorCode;
2011 return SOCKET_ERROR;
2012 }
2013
2014 /* Get the socket structure */
2015 Socket = SockFindAndReferenceSocket(Handle, TRUE);
2016 if (!Socket)
2017 {
2018 /* Fail */
2019 ErrorCode = WSAENOTSOCK;
2020 goto error;
2021 }
2022
2023 /*
2024 * Check if this isn't a datagram socket or if it's a connected socket
2025 * without an address
2026 */
2027 if (!MSAFD_IS_DGRAM_SOCK(Socket) ||
2028 ((Socket->SharedData.State == SocketConnected) &&
2029 (!SocketAddress || !SocketAddressLength)))
2030 {
2031 /* Call WSPSend instead */
2032 SockDereferenceSocket(Socket);
2033 return WSPSend(Handle,
2034 lpBuffers,
2035 dwBufferCount,
2036 lpNumberOfBytesSent,
2037 iFlags,
2038 lpOverlapped,
2039 lpCompletionRoutine,
2040 lpThreadId,
2041 lpErrno);
2042 }
2043
2044 /* If the socket isn't connected, we need an address*/
2045 if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress))
2046 {
2047 /* Fail */
2048 ErrorCode = WSAENOTCONN;
2049 goto error;
2050 }
2051
2052 /* Validate length */
2053 if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength)
2054 {
2055 /* Fail */
2056 ErrorCode = WSAEFAULT;
2057 goto error;
2058 }
2059
2060 /* Verify flags */
2061 if (iFlags & ~MSG_DONTROUTE)
2062 {
2063 /* Fail */
2064 ErrorCode = WSAEOPNOTSUPP;
2065 goto error;
2066 }
2067
2068 /* Make sure send shutdown isn't active */
2069 if (Socket->SharedData.SendShutdown)
2070 {
2071 /* Fail */
2072 ErrorCode = WSAESHUTDOWN;
2073 goto error;
2074 }
2075
2076 /* Make sure address families match */
2077 if (Socket->SharedData.AddressFamily != SocketAddress->sa_family)
2078 {
2079 /* Fail */
2080 ErrorCode = WSAEOPNOTSUPP;
2081 goto error;
2082 }
2083
2084 /* Check if broadcast is enabled */
2085 if (!Socket->SharedData.Broadcast)
2086 {
2087 /* The caller might want to enable it; get the Sockaddr type */
2088 ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress,
2089 SocketAddressLength,
2090 &SocketInfo);
2091 if (ErrorCode != NO_ERROR) goto error;
2092
2093 /* Check if this is a broadcast attempt */
2094 if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast)
2095 {
2096 /* The socket won't allow it */
2097 ErrorCode = WSAEACCES;
2098 goto error;
2099 }
2100 }
2101
2102 /* Check if this socket isn't bound yet */
2103 if (Socket->SharedData.State == SocketOpen)
2104 {
2105 /* Check if we can request the wildcard address */
2106 if (Socket->HelperData->WSHGetWildcardSockaddr)
2107 {
2108 /* Allocate a new Sockaddr */
2109 SockaddrLength = Socket->HelperData->MaxWSAddressLength;
2110 Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength);
2111 if (!Sockaddr)
2112 {
2113 /* Fail */
2114 ErrorCode = WSAENOBUFS;
2115 goto error;
2116 }
2117
2118 /* Get the wildcard sockaddr */
2119 ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
2120 Sockaddr,
2121 &SockaddrLength);
2122 if (ErrorCode != NO_ERROR)
2123 {
2124 /* Free memory and fail */
2125 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
2126 goto error;
2127 }
2128
2129 /* Lock the socket */
2130 EnterCriticalSection(&Socket->Lock);
2131
2132 /* Make sure it's still unbound */
2133 if (Socket->SharedData.State == SocketOpen)
2134 {
2135 /* Bind it */
2136 ReturnValue = WSPBind(Handle,
2137 Sockaddr,
2138 SockaddrLength,
2139 &ErrorCode);
2140 }
2141 else
2142 {
2143 /* It's bound now, fake success */
2144 ReturnValue = NO_ERROR;
2145 }
2146
2147 /* Release the lock and free memory */
2148 LeaveCriticalSection(&Socket->Lock);
2149 RtlFreeHeap(SockPrivateHeap, 0, Sockaddr);
2150
2151 /* Check if we failed */
2152 if (ReturnValue == SOCKET_ERROR) goto error;
2153 }
2154 else
2155 {
2156 /* Unbound socket, but can't get the wildcard. Fail */
2157 ErrorCode = WSAEINVAL;
2158 goto error;
2159 }
2160 }
2161
2162 /* Check how long the TDI Address is */
2163 TdiAddressSize = Socket->HelperData->MaxTDIAddressLength;
2164
2165 /* See if it can fit in the stack */
2166 if (TdiAddressSize > sizeof(AddressBuffer))
2167 {
2168 /* Allocate from heap */
2169 TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize);
2170 if (!TdiAddress)
2171 {
2172 /* Fail */
2173 ErrorCode = WSAENOBUFS;
2174 goto error;
2175 }
2176 }
2177
2178 /* Build the TDI Address */
2179 ErrorCode = SockBuildTdiAddress(TdiAddress,
2180 (PSOCKADDR)SocketAddress,
2181 min(SocketAddressLength,
2182 Socket->HelperData->MaxWSAddressLength));
2183 if (ErrorCode != NO_ERROR) goto error;
2184
2185 /* Set up the Send Structure */
2186 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
2187 SendInfo.BufferCount = dwBufferCount;
2188 SendInfo.AfdFlags = 0;
2189 SendInfo.TdiConnection.RemoteAddress = TdiAddress;
2190 SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize;
2191
2192 /* Verifiy if we should use APC */
2193 if (!lpOverlapped)
2194 {
2195 /* Not using Overlapped structure, so use normal blocking on event */
2196 APCContext = NULL;
2197 ApcFunction = NULL;
2198 Event = ThreadData->EventHandle;
2199 IoStatusBlock = &DummyIoStatusBlock;
2200 }
2201 else
2202 {
2203 /* Using apc, check if we have a completion routine */
2204 if (!lpCompletionRoutine)
2205 {
2206 /* No need for APC */
2207 APCContext = lpOverlapped;
2208 ApcFunction = NULL;
2209 Event = lpOverlapped->hEvent;
2210 }
2211 else
2212 {
2213 /* Use APC */
2214 ApcFunction = SockIoCompletion;
2215 APCContext = lpCompletionRoutine;
2216 Event = NULL;
2217
2218 /* Skip Fast I/O */
2219 SendInfo.AfdFlags = AFD_SKIP_FIO;
2220 }
2221
2222 /* Use the overlapped's structure buffer for the I/O Status Block */
2223 IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
2224
2225 /* Make this an overlapped I/O in AFD */
2226 SendInfo.AfdFlags |= AFD_OVERLAPPED;
2227 }
2228
2229 /* Set is as Pending for now */
2230 IoStatusBlock->Status = STATUS_PENDING;
2231
2232 /* Send IOCTL */
2233 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2234 Event,
2235 ApcFunction,
2236 APCContext,
2237 IoStatusBlock,
2238 IOCTL_AFD_SEND_DATAGRAM,
2239 &SendInfo,
2240 sizeof(SendInfo),
2241 NULL,
2242 0);
2243
2244 /* Increase the pending APC Count if we're using an APC */
2245 if (!NT_ERROR(Status) && ApcFunction)
2246 {
2247 ThreadData->PendingAPCs++;
2248 InterlockedIncrement(&SockProcessPendingAPCCount);
2249 }
2250
2251 /* Wait for completition if not overlapped */
2252 if ((Status == STATUS_PENDING) && !(lpOverlapped))
2253 {
2254 /* Wait for completion */
2255 ReturnValue = SockWaitForSingleObject(Event,
2256 Handle,
2257 MAYBE_BLOCKING_HOOK,
2258 SEND_TIMEOUT);
2259
2260 /* Check if the wait was successful */
2261 if (ReturnValue)
2262 {
2263 /* Get new status */
2264 Status = IoStatusBlock->Status;
2265 }
2266 else
2267 {
2268 /* Cancel the I/O */
2269 SockCancelIo(Handle);
2270 Status = STATUS_IO_TIMEOUT;
2271 }
2272 }
2273
2274 /* Check status */
2275 switch (Status)
2276 {
2277 /* Success */
2278 case STATUS_SUCCESS:
2279 break;
2280
2281 /* Pending I/O */
2282 case STATUS_PENDING:
2283 ErrorCode = WSA_IO_PENDING;
2284 goto error;
2285
2286 /* Other NT Error */
2287 default:
2288 if (!NT_SUCCESS(Status))
2289 {
2290 /* Fail */
2291 ErrorCode = NtStatusToSocketError(Status);
2292 goto error;
2293 }
2294 break;
2295 }
2296
2297 /* Return the number of bytes sent */
2298 *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information);
2299
2300 error:
2301
2302 /* Check if we have a socket */
2303 if (Socket)
2304 {
2305 /* Check if async select was active and this blocked */
2306 if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK))
2307 {
2308 /* Lock it */
2309 EnterCriticalSection(&Socket->Lock);
2310
2311 /* Re-enable the regular write event */
2312 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
2313
2314 /* Unlock socket */
2315 LeaveCriticalSection(&Socket->Lock);
2316 }
2317
2318 /* Dereference socket */
2319 SockDereferenceSocket(Socket);
2320 }
2321
2322 /* Check if we should free the TDI Address */
2323 if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer))
2324 {
2325 /* Free it from the heap */
2326 RtlFreeHeap(SockPrivateHeap, 0, TdiAddress);
2327 }
2328
2329 /* Check for error */
2330 if (ErrorCode != NO_ERROR)
2331 {
2332 /* Fail */
2333 *lpErrno = ErrorCode;
2334 return SOCKET_ERROR;
2335 }
2336
2337 /* Return success */
2338 return NO_ERROR;
2339 }
2340