1c2c66affSColin Finck /* 2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3c2c66affSColin Finck * PROJECT: ReactOS Ancillary Function Driver DLL 4c2c66affSColin Finck * FILE: dll/win32/msafd/misc/sndrcv.c 5c2c66affSColin Finck * PURPOSE: Send/receive routines 6c2c66affSColin Finck * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7c2c66affSColin Finck * Alex Ionescu (alex@relsoft.net) 8c2c66affSColin Finck * REVISIONS: 9c2c66affSColin Finck * CSH 01/09-2000 Created 10c2c66affSColin Finck * Alex 16/07/2004 - Complete Rewrite 11c2c66affSColin Finck */ 12c2c66affSColin Finck 13c2c66affSColin Finck #include <msafd.h> 14c2c66affSColin Finck 15c2c66affSColin Finck INT 16c2c66affSColin Finck WSPAPI 17c2c66affSColin Finck WSPAsyncSelect(IN SOCKET Handle, 18c2c66affSColin Finck IN HWND hWnd, 19c2c66affSColin Finck IN UINT wMsg, 20c2c66affSColin Finck IN LONG lEvent, 21c2c66affSColin Finck OUT LPINT lpErrno) 22c2c66affSColin Finck { 23c2c66affSColin Finck PSOCKET_INFORMATION Socket = NULL; 24c2c66affSColin Finck PASYNC_DATA AsyncData; 25c2c66affSColin Finck BOOLEAN BlockMode; 26c2c66affSColin Finck 27c2c66affSColin Finck /* Get the Socket Structure associated to this Socket */ 28c2c66affSColin Finck Socket = GetSocketStructure(Handle); 29c2c66affSColin Finck if (!Socket) 30c2c66affSColin Finck { 31c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 32c2c66affSColin Finck return SOCKET_ERROR; 33c2c66affSColin Finck } 34c2c66affSColin Finck 35c2c66affSColin Finck /* Allocate the Async Data Structure to pass on to the Thread later */ 36c2c66affSColin Finck AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData)); 37c2c66affSColin Finck if (!AsyncData) 38c2c66affSColin Finck { 39c2c66affSColin Finck MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); 40c2c66affSColin Finck return INVALID_SOCKET; 41c2c66affSColin Finck } 42c2c66affSColin Finck 43c2c66affSColin Finck /* Change the Socket to Non Blocking */ 44c2c66affSColin Finck BlockMode = TRUE; 45c2c66affSColin Finck SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL, NULL, NULL); 46c2c66affSColin Finck Socket->SharedData->NonBlocking = TRUE; 47c2c66affSColin Finck 48c2c66affSColin Finck /* Deactivate WSPEventSelect */ 49c2c66affSColin Finck if (Socket->SharedData->AsyncEvents) 50c2c66affSColin Finck { 51c2c66affSColin Finck if (WSPEventSelect(Handle, NULL, 0, lpErrno) == SOCKET_ERROR) 52c2c66affSColin Finck { 53c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, AsyncData); 54c2c66affSColin Finck return SOCKET_ERROR; 55c2c66affSColin Finck } 56c2c66affSColin Finck } 57c2c66affSColin Finck 58c2c66affSColin Finck /* Create the Asynch Thread if Needed */ 59c2c66affSColin Finck SockCreateOrReferenceAsyncThread(); 60c2c66affSColin Finck 61c2c66affSColin Finck /* Open a Handle to AFD's Async Helper */ 62c2c66affSColin Finck SockGetAsyncSelectHelperAfdHandle(); 63c2c66affSColin Finck 64c2c66affSColin Finck /* Store Socket Data */ 65c2c66affSColin Finck Socket->SharedData->hWnd = hWnd; 66c2c66affSColin Finck Socket->SharedData->wMsg = wMsg; 67c2c66affSColin Finck Socket->SharedData->AsyncEvents = lEvent; 68c2c66affSColin Finck Socket->SharedData->AsyncDisabledEvents = 0; 69c2c66affSColin Finck Socket->SharedData->SequenceNumber++; 70c2c66affSColin Finck 71c2c66affSColin Finck /* Return if there are no more Events */ 72c2c66affSColin Finck if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0) 73c2c66affSColin Finck { 74c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, AsyncData); 75c2c66affSColin Finck return 0; 76c2c66affSColin Finck } 77c2c66affSColin Finck 78c2c66affSColin Finck /* Set up the Async Data */ 79c2c66affSColin Finck AsyncData->ParentSocket = Socket; 80c2c66affSColin Finck AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber; 81c2c66affSColin Finck 82c2c66affSColin Finck /* Begin Async Select by using I/O Completion */ 83c2c66affSColin Finck NtSetIoCompletion(SockAsyncCompletionPort, 84c2c66affSColin Finck (PVOID)&SockProcessQueuedAsyncSelect, 85c2c66affSColin Finck AsyncData, 86c2c66affSColin Finck 0, 87c2c66affSColin Finck 0); 88c2c66affSColin Finck 89c2c66affSColin Finck /* Return */ 90c2c66affSColin Finck return ERROR_SUCCESS; 91c2c66affSColin Finck } 92c2c66affSColin Finck 93c2c66affSColin Finck 94c2c66affSColin Finck BOOL 95c2c66affSColin Finck WSPAPI 96c2c66affSColin Finck WSPGetOverlappedResult( 97c2c66affSColin Finck IN SOCKET Handle, 98c2c66affSColin Finck IN LPWSAOVERLAPPED lpOverlapped, 99c2c66affSColin Finck OUT LPDWORD lpdwBytes, 100c2c66affSColin Finck IN BOOL fWait, 101c2c66affSColin Finck OUT LPDWORD lpdwFlags, 102c2c66affSColin Finck OUT LPINT lpErrno) 103c2c66affSColin Finck { 104c2c66affSColin Finck PSOCKET_INFORMATION Socket; 105c2c66affSColin Finck BOOL Ret; 106c2c66affSColin Finck 107c2c66affSColin Finck TRACE("Called (%x)\n", Handle); 108c2c66affSColin Finck 109c2c66affSColin Finck /* Get the Socket Structure associate to this Socket*/ 110c2c66affSColin Finck Socket = GetSocketStructure(Handle); 111c2c66affSColin Finck if (!Socket) 112c2c66affSColin Finck { 113c2c66affSColin Finck if(lpErrno) 114c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 115c2c66affSColin Finck return FALSE; 116c2c66affSColin Finck } 117c2c66affSColin Finck if (!lpOverlapped || !lpdwBytes || !lpdwFlags) 118c2c66affSColin Finck { 119c2c66affSColin Finck if (lpErrno) 120c2c66affSColin Finck *lpErrno = WSAEFAULT; 121c2c66affSColin Finck return FALSE; 122c2c66affSColin Finck } 123c2c66affSColin Finck Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait); 124c2c66affSColin Finck 125c2c66affSColin Finck if (Ret) 126c2c66affSColin Finck { 127c2c66affSColin Finck *lpdwFlags = 0; 128c2c66affSColin Finck 129c2c66affSColin Finck /* Re-enable Async Event */ 130c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_OOB); 131c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_WRITE); 132c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_READ); 133c2c66affSColin Finck } 134c2c66affSColin Finck 135c2c66affSColin Finck return Ret; 136c2c66affSColin Finck } 137c2c66affSColin Finck 138c2c66affSColin Finck VOID 139c2c66affSColin Finck NTAPI 140c2c66affSColin Finck AfdAPC(PVOID ApcContext, 141c2c66affSColin Finck PIO_STATUS_BLOCK IoStatusBlock, 142c2c66affSColin Finck ULONG Reserved) 143c2c66affSColin Finck { 144c2c66affSColin Finck PAFDAPCCONTEXT Context = ApcContext; 145c2c66affSColin Finck 146c2c66affSColin Finck /* Re-enable Async Event */ 147c2c66affSColin Finck SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB); 148c2c66affSColin Finck SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ); 149c2c66affSColin Finck SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE); 150c2c66affSColin Finck 151c2c66affSColin Finck Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); 152c2c66affSColin Finck HeapFree(GlobalHeap, 0, ApcContext); 153c2c66affSColin Finck } 154c2c66affSColin Finck 155c2c66affSColin Finck int 156c2c66affSColin Finck WSPAPI 157c2c66affSColin Finck WSPRecv(SOCKET Handle, 158c2c66affSColin Finck LPWSABUF lpBuffers, 159c2c66affSColin Finck DWORD dwBufferCount, 160c2c66affSColin Finck LPDWORD lpNumberOfBytesRead, 161c2c66affSColin Finck LPDWORD ReceiveFlags, 162c2c66affSColin Finck LPWSAOVERLAPPED lpOverlapped, 163c2c66affSColin Finck LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 164c2c66affSColin Finck LPWSATHREADID lpThreadId, 165c2c66affSColin Finck LPINT lpErrno) 166c2c66affSColin Finck { 167c2c66affSColin Finck PIO_STATUS_BLOCK IOSB; 168c2c66affSColin Finck IO_STATUS_BLOCK DummyIOSB; 169c2c66affSColin Finck AFD_RECV_INFO RecvInfo; 170c2c66affSColin Finck NTSTATUS Status; 171c2c66affSColin Finck PVOID APCContext; 172c2c66affSColin Finck PIO_APC_ROUTINE APCFunction; 173c2c66affSColin Finck HANDLE Event = NULL; 174c2c66affSColin Finck HANDLE SockEvent; 175c2c66affSColin Finck PSOCKET_INFORMATION Socket; 176c2c66affSColin Finck 177c2c66affSColin Finck TRACE("Called (%x)\n", Handle); 178c2c66affSColin Finck 179c2c66affSColin Finck /* Get the Socket Structure associate to this Socket*/ 180c2c66affSColin Finck Socket = GetSocketStructure(Handle); 181c2c66affSColin Finck if (!Socket) 182c2c66affSColin Finck { 183c2c66affSColin Finck if (lpErrno) 184c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 185c2c66affSColin Finck return SOCKET_ERROR; 186c2c66affSColin Finck } 187c2c66affSColin Finck if (!lpNumberOfBytesRead && !lpOverlapped) 188c2c66affSColin Finck { 189c2c66affSColin Finck if (lpErrno) 190c2c66affSColin Finck *lpErrno = WSAEFAULT; 191c2c66affSColin Finck return SOCKET_ERROR; 192c2c66affSColin Finck } 193c2c66affSColin Finck if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0) 194c2c66affSColin Finck { 195c2c66affSColin Finck if (lpErrno) 196c2c66affSColin Finck *lpErrno = WSAEINVAL; 197c2c66affSColin Finck return SOCKET_ERROR; 198c2c66affSColin Finck } 199c2c66affSColin Finck 200c2c66affSColin Finck Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, 201*bf5e3320SThomas Faber NULL, SynchronizationEvent, FALSE ); 202c2c66affSColin Finck 203c2c66affSColin Finck if( !NT_SUCCESS(Status) ) 204c2c66affSColin Finck return -1; 205c2c66affSColin Finck 206c2c66affSColin Finck /* Set up the Receive Structure */ 207c2c66affSColin Finck RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; 208c2c66affSColin Finck RecvInfo.BufferCount = dwBufferCount; 209c2c66affSColin Finck RecvInfo.TdiFlags = 0; 210c2c66affSColin Finck RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; 211c2c66affSColin Finck 212c2c66affSColin Finck /* Set the TDI Flags */ 213c2c66affSColin Finck if (*ReceiveFlags == 0) 214c2c66affSColin Finck { 215c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; 216c2c66affSColin Finck } 217c2c66affSColin Finck else 218c2c66affSColin Finck { 219c2c66affSColin Finck if (*ReceiveFlags & MSG_OOB) 220c2c66affSColin Finck { 221c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; 222c2c66affSColin Finck } 223c2c66affSColin Finck 224c2c66affSColin Finck if (*ReceiveFlags & MSG_PEEK) 225c2c66affSColin Finck { 226c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; 227c2c66affSColin Finck } 228c2c66affSColin Finck 229c2c66affSColin Finck if (*ReceiveFlags & MSG_PARTIAL) 230c2c66affSColin Finck { 231c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; 232c2c66affSColin Finck } 233c2c66affSColin Finck } 234c2c66affSColin Finck 235c2c66affSColin Finck /* Verify if we should use APC */ 236c2c66affSColin Finck 237c2c66affSColin Finck if (lpOverlapped == NULL) 238c2c66affSColin Finck { 239c2c66affSColin Finck /* Not using Overlapped structure, so use normal blocking on event */ 240c2c66affSColin Finck APCContext = NULL; 241c2c66affSColin Finck APCFunction = NULL; 242c2c66affSColin Finck Event = SockEvent; 243c2c66affSColin Finck IOSB = &DummyIOSB; 244c2c66affSColin Finck } 245c2c66affSColin Finck else 246c2c66affSColin Finck { 247c2c66affSColin Finck /* Overlapped request for non overlapped opened socket */ 248c2c66affSColin Finck if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 249c2c66affSColin Finck { 250c2c66affSColin Finck TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 251c2c66affSColin Finck return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); 252c2c66affSColin Finck } 253c2c66affSColin Finck if (lpCompletionRoutine == NULL) 254c2c66affSColin Finck { 255c2c66affSColin Finck /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ 256c2c66affSColin Finck APCContext = lpOverlapped; 257c2c66affSColin Finck APCFunction = NULL; 258c2c66affSColin Finck Event = lpOverlapped->hEvent; 259c2c66affSColin Finck } 260c2c66affSColin Finck else 261c2c66affSColin Finck { 262c2c66affSColin Finck /* Using Overlapped Structure and a Completion Routine, so use an APC */ 263c2c66affSColin Finck APCFunction = &AfdAPC; // should be a private io completion function inside us 264c2c66affSColin Finck APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 265c2c66affSColin Finck if (!APCContext) 266c2c66affSColin Finck { 267c2c66affSColin Finck ERR("Not enough memory for APC Context\n"); 268c2c66affSColin Finck return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead); 269c2c66affSColin Finck } 270c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; 271c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; 272c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; 273c2c66affSColin Finck RecvInfo.AfdFlags |= AFD_SKIP_FIO; 274c2c66affSColin Finck } 275c2c66affSColin Finck 276c2c66affSColin Finck IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; 277c2c66affSColin Finck RecvInfo.AfdFlags |= AFD_OVERLAPPED; 278c2c66affSColin Finck } 279c2c66affSColin Finck 280c2c66affSColin Finck IOSB->Status = STATUS_PENDING; 281c2c66affSColin Finck 282c2c66affSColin Finck /* Send IOCTL */ 283c2c66affSColin Finck Status = NtDeviceIoControlFile((HANDLE)Handle, 284c2c66affSColin Finck Event, 285c2c66affSColin Finck APCFunction, 286c2c66affSColin Finck APCContext, 287c2c66affSColin Finck IOSB, 288c2c66affSColin Finck IOCTL_AFD_RECV, 289c2c66affSColin Finck &RecvInfo, 290c2c66affSColin Finck sizeof(RecvInfo), 291c2c66affSColin Finck NULL, 292c2c66affSColin Finck 0); 293c2c66affSColin Finck 294c2c66affSColin Finck /* Wait for completion of not overlapped */ 295c2c66affSColin Finck if (Status == STATUS_PENDING && lpOverlapped == NULL) 296c2c66affSColin Finck { 297c2c66affSColin Finck /* It's up to the protocol to time out recv. We must wait 298c2c66affSColin Finck * until the protocol decides it's had enough. 299c2c66affSColin Finck */ 300c2c66affSColin Finck WaitForSingleObject(SockEvent, INFINITE); 301c2c66affSColin Finck Status = IOSB->Status; 302c2c66affSColin Finck } 303c2c66affSColin Finck 304c2c66affSColin Finck NtClose( SockEvent ); 305c2c66affSColin Finck 306c2c66affSColin Finck TRACE("Status %x Information %d\n", Status, IOSB->Information); 307c2c66affSColin Finck 308c2c66affSColin Finck if (Status == STATUS_PENDING) 309c2c66affSColin Finck { 310c2c66affSColin Finck TRACE("Leaving (Pending)\n"); 311c2c66affSColin Finck return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); 312c2c66affSColin Finck } 313c2c66affSColin Finck 314c2c66affSColin Finck /* Return the Flags */ 315c2c66affSColin Finck *ReceiveFlags = 0; 316c2c66affSColin Finck 317c2c66affSColin Finck switch (Status) 318c2c66affSColin Finck { 319c2c66affSColin Finck case STATUS_RECEIVE_EXPEDITED: 320c2c66affSColin Finck *ReceiveFlags = MSG_OOB; 321c2c66affSColin Finck break; 322c2c66affSColin Finck case STATUS_RECEIVE_PARTIAL_EXPEDITED: 323c2c66affSColin Finck *ReceiveFlags = MSG_PARTIAL | MSG_OOB; 324c2c66affSColin Finck break; 325c2c66affSColin Finck case STATUS_RECEIVE_PARTIAL: 326c2c66affSColin Finck *ReceiveFlags = MSG_PARTIAL; 327c2c66affSColin Finck break; 328c2c66affSColin Finck } 329c2c66affSColin Finck 330c2c66affSColin Finck /* Re-enable Async Event */ 331c2c66affSColin Finck if (*ReceiveFlags & MSG_OOB) 332c2c66affSColin Finck { 333c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_OOB); 334c2c66affSColin Finck } 335c2c66affSColin Finck else 336c2c66affSColin Finck { 337c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_READ); 338c2c66affSColin Finck } 339c2c66affSColin Finck 340c2c66affSColin Finck if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) 341c2c66affSColin Finck { 342c2c66affSColin Finck lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); 343c2c66affSColin Finck HeapFree(GlobalHeap, 0, (PVOID)APCContext); 344c2c66affSColin Finck } 345c2c66affSColin Finck 346c2c66affSColin Finck return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); 347c2c66affSColin Finck } 348c2c66affSColin Finck 349c2c66affSColin Finck int 350c2c66affSColin Finck WSPAPI 351c2c66affSColin Finck WSPRecvFrom(SOCKET Handle, 352c2c66affSColin Finck LPWSABUF lpBuffers, 353c2c66affSColin Finck DWORD dwBufferCount, 354c2c66affSColin Finck LPDWORD lpNumberOfBytesRead, 355c2c66affSColin Finck LPDWORD ReceiveFlags, 356c2c66affSColin Finck struct sockaddr *SocketAddress, 357c2c66affSColin Finck int *SocketAddressLength, 358c2c66affSColin Finck LPWSAOVERLAPPED lpOverlapped, 359c2c66affSColin Finck LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 360c2c66affSColin Finck LPWSATHREADID lpThreadId, 361c2c66affSColin Finck LPINT lpErrno ) 362c2c66affSColin Finck { 363c2c66affSColin Finck PIO_STATUS_BLOCK IOSB; 364c2c66affSColin Finck IO_STATUS_BLOCK DummyIOSB; 365c2c66affSColin Finck AFD_RECV_INFO_UDP RecvInfo; 366c2c66affSColin Finck NTSTATUS Status; 367c2c66affSColin Finck PVOID APCContext; 368c2c66affSColin Finck PVOID APCFunction; 369c2c66affSColin Finck HANDLE Event = NULL; 370c2c66affSColin Finck HANDLE SockEvent; 371c2c66affSColin Finck PSOCKET_INFORMATION Socket; 372c2c66affSColin Finck 373c2c66affSColin Finck /* Get the Socket Structure associate to this Socket*/ 374c2c66affSColin Finck Socket = GetSocketStructure(Handle); 375c2c66affSColin Finck if (!Socket) 376c2c66affSColin Finck { 377c2c66affSColin Finck if (lpErrno) 378c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 379c2c66affSColin Finck return SOCKET_ERROR; 380c2c66affSColin Finck } 381c2c66affSColin Finck if (!lpNumberOfBytesRead && !lpOverlapped) 382c2c66affSColin Finck { 383c2c66affSColin Finck if (lpErrno) 384c2c66affSColin Finck *lpErrno = WSAEFAULT; 385c2c66affSColin Finck return SOCKET_ERROR; 386c2c66affSColin Finck } 387c2c66affSColin Finck if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0) 388c2c66affSColin Finck { 389c2c66affSColin Finck if (lpErrno) 390c2c66affSColin Finck *lpErrno = WSAEINVAL; 391c2c66affSColin Finck return SOCKET_ERROR; 392c2c66affSColin Finck } 393c2c66affSColin Finck 394c2c66affSColin Finck if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS)) 395c2c66affSColin Finck { 396c2c66affSColin Finck /* Call WSPRecv for a non-datagram socket */ 397c2c66affSColin Finck return WSPRecv(Handle, 398c2c66affSColin Finck lpBuffers, 399c2c66affSColin Finck dwBufferCount, 400c2c66affSColin Finck lpNumberOfBytesRead, 401c2c66affSColin Finck ReceiveFlags, 402c2c66affSColin Finck lpOverlapped, 403c2c66affSColin Finck lpCompletionRoutine, 404c2c66affSColin Finck lpThreadId, 405c2c66affSColin Finck lpErrno); 406c2c66affSColin Finck } 407c2c66affSColin Finck 408c2c66affSColin Finck /* Bind us First */ 409c2c66affSColin Finck if (Socket->SharedData->State == SocketOpen) 410c2c66affSColin Finck { 411c2c66affSColin Finck Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, 412c2c66affSColin Finck SocketAddress, 413c2c66affSColin Finck SocketAddressLength); 414c2c66affSColin Finck /* Bind it */ 415c2c66affSColin Finck if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR) 416c2c66affSColin Finck return SOCKET_ERROR; 417c2c66affSColin Finck } 418c2c66affSColin Finck 419c2c66affSColin Finck Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, 420*bf5e3320SThomas Faber NULL, SynchronizationEvent, FALSE ); 421c2c66affSColin Finck 422c2c66affSColin Finck if( !NT_SUCCESS(Status) ) 423c2c66affSColin Finck return -1; 424c2c66affSColin Finck 425c2c66affSColin Finck /* Set up the Receive Structure */ 426c2c66affSColin Finck RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; 427c2c66affSColin Finck RecvInfo.BufferCount = dwBufferCount; 428c2c66affSColin Finck RecvInfo.TdiFlags = 0; 429c2c66affSColin Finck RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; 430c2c66affSColin Finck RecvInfo.AddressLength = SocketAddressLength; 431c2c66affSColin Finck RecvInfo.Address = SocketAddress; 432c2c66affSColin Finck 433c2c66affSColin Finck /* Set the TDI Flags */ 434c2c66affSColin Finck if (*ReceiveFlags == 0) 435c2c66affSColin Finck { 436c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; 437c2c66affSColin Finck } 438c2c66affSColin Finck else 439c2c66affSColin Finck { 440c2c66affSColin Finck if (*ReceiveFlags & MSG_OOB) 441c2c66affSColin Finck { 442c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; 443c2c66affSColin Finck } 444c2c66affSColin Finck 445c2c66affSColin Finck if (*ReceiveFlags & MSG_PEEK) 446c2c66affSColin Finck { 447c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; 448c2c66affSColin Finck } 449c2c66affSColin Finck 450c2c66affSColin Finck if (*ReceiveFlags & MSG_PARTIAL) 451c2c66affSColin Finck { 452c2c66affSColin Finck RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; 453c2c66affSColin Finck } 454c2c66affSColin Finck } 455c2c66affSColin Finck 456c2c66affSColin Finck /* Verify if we should use APC */ 457c2c66affSColin Finck 458c2c66affSColin Finck if (lpOverlapped == NULL) 459c2c66affSColin Finck { 460c2c66affSColin Finck /* Not using Overlapped structure, so use normal blocking on event */ 461c2c66affSColin Finck APCContext = NULL; 462c2c66affSColin Finck APCFunction = NULL; 463c2c66affSColin Finck Event = SockEvent; 464c2c66affSColin Finck IOSB = &DummyIOSB; 465c2c66affSColin Finck } 466c2c66affSColin Finck else 467c2c66affSColin Finck { 468c2c66affSColin Finck /* Overlapped request for non overlapped opened socket */ 469c2c66affSColin Finck if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 470c2c66affSColin Finck { 471c2c66affSColin Finck TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 472c2c66affSColin Finck return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); 473c2c66affSColin Finck } 474c2c66affSColin Finck if (lpCompletionRoutine == NULL) 475c2c66affSColin Finck { 476c2c66affSColin Finck /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ 477c2c66affSColin Finck APCContext = lpOverlapped; 478c2c66affSColin Finck APCFunction = NULL; 479c2c66affSColin Finck Event = lpOverlapped->hEvent; 480c2c66affSColin Finck } 481c2c66affSColin Finck else 482c2c66affSColin Finck { 483c2c66affSColin Finck /* Using Overlapped Structure and a Completion Routine, so use an APC */ 484c2c66affSColin Finck APCFunction = &AfdAPC; // should be a private io completion function inside us 485c2c66affSColin Finck APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 486c2c66affSColin Finck if (!APCContext) 487c2c66affSColin Finck { 488c2c66affSColin Finck ERR("Not enough memory for APC Context\n"); 489c2c66affSColin Finck return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead); 490c2c66affSColin Finck } 491c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; 492c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; 493c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; 494c2c66affSColin Finck RecvInfo.AfdFlags |= AFD_SKIP_FIO; 495c2c66affSColin Finck } 496c2c66affSColin Finck 497c2c66affSColin Finck IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; 498c2c66affSColin Finck RecvInfo.AfdFlags |= AFD_OVERLAPPED; 499c2c66affSColin Finck } 500c2c66affSColin Finck 501c2c66affSColin Finck IOSB->Status = STATUS_PENDING; 502c2c66affSColin Finck 503c2c66affSColin Finck /* Send IOCTL */ 504c2c66affSColin Finck Status = NtDeviceIoControlFile((HANDLE)Handle, 505c2c66affSColin Finck Event, 506c2c66affSColin Finck APCFunction, 507c2c66affSColin Finck APCContext, 508c2c66affSColin Finck IOSB, 509c2c66affSColin Finck IOCTL_AFD_RECV_DATAGRAM, 510c2c66affSColin Finck &RecvInfo, 511c2c66affSColin Finck sizeof(RecvInfo), 512c2c66affSColin Finck NULL, 513c2c66affSColin Finck 0); 514c2c66affSColin Finck 515c2c66affSColin Finck /* Wait for completion of not overlapped */ 516c2c66affSColin Finck if (Status == STATUS_PENDING && lpOverlapped == NULL) 517c2c66affSColin Finck { 518c2c66affSColin Finck WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive... 519c2c66affSColin Finck Status = IOSB->Status; 520c2c66affSColin Finck } 521c2c66affSColin Finck 522c2c66affSColin Finck NtClose( SockEvent ); 523c2c66affSColin Finck 524c2c66affSColin Finck if (Status == STATUS_PENDING) 525c2c66affSColin Finck { 526c2c66affSColin Finck TRACE("Leaving (Pending)\n"); 527c2c66affSColin Finck return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); 528c2c66affSColin Finck } 529c2c66affSColin Finck 530c2c66affSColin Finck /* Return the Flags */ 531c2c66affSColin Finck *ReceiveFlags = 0; 532c2c66affSColin Finck 533c2c66affSColin Finck switch (Status) 534c2c66affSColin Finck { 535c2c66affSColin Finck case STATUS_RECEIVE_EXPEDITED: 536c2c66affSColin Finck *ReceiveFlags = MSG_OOB; 537c2c66affSColin Finck break; 538c2c66affSColin Finck case STATUS_RECEIVE_PARTIAL_EXPEDITED: 539c2c66affSColin Finck *ReceiveFlags = MSG_PARTIAL | MSG_OOB; 540c2c66affSColin Finck break; 541c2c66affSColin Finck case STATUS_RECEIVE_PARTIAL: 542c2c66affSColin Finck *ReceiveFlags = MSG_PARTIAL; 543c2c66affSColin Finck break; 544c2c66affSColin Finck } 545c2c66affSColin Finck 546c2c66affSColin Finck /* Re-enable Async Event */ 547c2c66affSColin Finck if (*ReceiveFlags & MSG_OOB) 548c2c66affSColin Finck { 549c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_OOB); 550c2c66affSColin Finck } 551c2c66affSColin Finck else 552c2c66affSColin Finck { 553c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_READ); 554c2c66affSColin Finck } 555c2c66affSColin Finck 556c2c66affSColin Finck if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) 557c2c66affSColin Finck { 558c2c66affSColin Finck lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); 559c2c66affSColin Finck HeapFree(GlobalHeap, 0, (PVOID)APCContext); 560c2c66affSColin Finck } 561c2c66affSColin Finck 562c2c66affSColin Finck return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); 563c2c66affSColin Finck } 564c2c66affSColin Finck 565c2c66affSColin Finck 566c2c66affSColin Finck int 567c2c66affSColin Finck WSPAPI 568c2c66affSColin Finck WSPSend(SOCKET Handle, 569c2c66affSColin Finck LPWSABUF lpBuffers, 570c2c66affSColin Finck DWORD dwBufferCount, 571c2c66affSColin Finck LPDWORD lpNumberOfBytesSent, 572c2c66affSColin Finck DWORD iFlags, 573c2c66affSColin Finck LPWSAOVERLAPPED lpOverlapped, 574c2c66affSColin Finck LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 575c2c66affSColin Finck LPWSATHREADID lpThreadId, 576c2c66affSColin Finck LPINT lpErrno) 577c2c66affSColin Finck { 578c2c66affSColin Finck PIO_STATUS_BLOCK IOSB; 579c2c66affSColin Finck IO_STATUS_BLOCK DummyIOSB; 580c2c66affSColin Finck AFD_SEND_INFO SendInfo; 581c2c66affSColin Finck NTSTATUS Status; 582c2c66affSColin Finck PVOID APCContext; 583c2c66affSColin Finck PVOID APCFunction; 584c2c66affSColin Finck HANDLE Event = NULL; 585c2c66affSColin Finck HANDLE SockEvent; 586c2c66affSColin Finck PSOCKET_INFORMATION Socket; 587c2c66affSColin Finck 588c2c66affSColin Finck /* Get the Socket Structure associate to this Socket*/ 589c2c66affSColin Finck Socket = GetSocketStructure(Handle); 590c2c66affSColin Finck if (!Socket) 591c2c66affSColin Finck { 592c2c66affSColin Finck if (lpErrno) 593c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 594c2c66affSColin Finck return SOCKET_ERROR; 595c2c66affSColin Finck } 596c2c66affSColin Finck if (!lpNumberOfBytesSent && !lpOverlapped) 597c2c66affSColin Finck { 598c2c66affSColin Finck if (lpErrno) 599c2c66affSColin Finck *lpErrno = WSAEFAULT; 600c2c66affSColin Finck return SOCKET_ERROR; 601c2c66affSColin Finck } 602c2c66affSColin Finck 603c2c66affSColin Finck Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, 604*bf5e3320SThomas Faber NULL, SynchronizationEvent, FALSE ); 605c2c66affSColin Finck 606c2c66affSColin Finck if( !NT_SUCCESS(Status) ) 607c2c66affSColin Finck return -1; 608c2c66affSColin Finck 609c2c66affSColin Finck TRACE("Called\n"); 610c2c66affSColin Finck 611c2c66affSColin Finck /* Set up the Send Structure */ 612c2c66affSColin Finck SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; 613c2c66affSColin Finck SendInfo.BufferCount = dwBufferCount; 614c2c66affSColin Finck SendInfo.TdiFlags = 0; 615c2c66affSColin Finck SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; 616c2c66affSColin Finck 617c2c66affSColin Finck /* Set the TDI Flags */ 618c2c66affSColin Finck if (iFlags) 619c2c66affSColin Finck { 620c2c66affSColin Finck if (iFlags & MSG_OOB) 621c2c66affSColin Finck { 622c2c66affSColin Finck SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; 623c2c66affSColin Finck } 624c2c66affSColin Finck if (iFlags & MSG_PARTIAL) 625c2c66affSColin Finck { 626c2c66affSColin Finck SendInfo.TdiFlags |= TDI_SEND_PARTIAL; 627c2c66affSColin Finck } 628c2c66affSColin Finck } 629c2c66affSColin Finck 630c2c66affSColin Finck /* Verify if we should use APC */ 631c2c66affSColin Finck if (lpOverlapped == NULL) 632c2c66affSColin Finck { 633c2c66affSColin Finck /* Not using Overlapped structure, so use normal blocking on event */ 634c2c66affSColin Finck APCContext = NULL; 635c2c66affSColin Finck APCFunction = NULL; 636c2c66affSColin Finck Event = SockEvent; 637c2c66affSColin Finck IOSB = &DummyIOSB; 638c2c66affSColin Finck } 639c2c66affSColin Finck else 640c2c66affSColin Finck { 641c2c66affSColin Finck /* Overlapped request for non overlapped opened socket */ 642c2c66affSColin Finck if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 643c2c66affSColin Finck { 644c2c66affSColin Finck TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 645c2c66affSColin Finck return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); 646c2c66affSColin Finck } 647c2c66affSColin Finck if (lpCompletionRoutine == NULL) 648c2c66affSColin Finck { 649c2c66affSColin Finck /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ 650c2c66affSColin Finck APCContext = lpOverlapped; 651c2c66affSColin Finck APCFunction = NULL; 652c2c66affSColin Finck Event = lpOverlapped->hEvent; 653c2c66affSColin Finck } 654c2c66affSColin Finck else 655c2c66affSColin Finck { 656c2c66affSColin Finck /* Using Overlapped Structure and a Completion Routine, so use an APC */ 657c2c66affSColin Finck APCFunction = &AfdAPC; // should be a private io completion function inside us 658c2c66affSColin Finck APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 659c2c66affSColin Finck if (!APCContext) 660c2c66affSColin Finck { 661c2c66affSColin Finck ERR("Not enough memory for APC Context\n"); 662c2c66affSColin Finck return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent); 663c2c66affSColin Finck } 664c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; 665c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; 666c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; 667c2c66affSColin Finck SendInfo.AfdFlags |= AFD_SKIP_FIO; 668c2c66affSColin Finck } 669c2c66affSColin Finck 670c2c66affSColin Finck IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; 671c2c66affSColin Finck SendInfo.AfdFlags |= AFD_OVERLAPPED; 672c2c66affSColin Finck } 673c2c66affSColin Finck 674c2c66affSColin Finck IOSB->Status = STATUS_PENDING; 675c2c66affSColin Finck 676c2c66affSColin Finck /* Send IOCTL */ 677c2c66affSColin Finck Status = NtDeviceIoControlFile((HANDLE)Handle, 678c2c66affSColin Finck Event, 679c2c66affSColin Finck APCFunction, 680c2c66affSColin Finck APCContext, 681c2c66affSColin Finck IOSB, 682c2c66affSColin Finck IOCTL_AFD_SEND, 683c2c66affSColin Finck &SendInfo, 684c2c66affSColin Finck sizeof(SendInfo), 685c2c66affSColin Finck NULL, 686c2c66affSColin Finck 0); 687c2c66affSColin Finck 688c2c66affSColin Finck /* Wait for completion of not overlapped */ 689c2c66affSColin Finck if (Status == STATUS_PENDING && lpOverlapped == NULL) 690c2c66affSColin Finck { 691c2c66affSColin Finck WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send... 692c2c66affSColin Finck Status = IOSB->Status; 693c2c66affSColin Finck } 694c2c66affSColin Finck 695c2c66affSColin Finck NtClose( SockEvent ); 696c2c66affSColin Finck 697c2c66affSColin Finck if (Status == STATUS_PENDING) 698c2c66affSColin Finck { 699c2c66affSColin Finck TRACE("Leaving (Pending)\n"); 700c2c66affSColin Finck return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); 701c2c66affSColin Finck } 702c2c66affSColin Finck 703c2c66affSColin Finck /* Re-enable Async Event */ 704c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_WRITE); 705c2c66affSColin Finck 706c2c66affSColin Finck TRACE("Leaving (Success, %d)\n", IOSB->Information); 707c2c66affSColin Finck 708c2c66affSColin Finck if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) 709c2c66affSColin Finck { 710c2c66affSColin Finck lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); 711c2c66affSColin Finck HeapFree(GlobalHeap, 0, (PVOID)APCContext); 712c2c66affSColin Finck } 713c2c66affSColin Finck 714c2c66affSColin Finck return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent ); 715c2c66affSColin Finck } 716c2c66affSColin Finck 717c2c66affSColin Finck int 718c2c66affSColin Finck WSPAPI 719c2c66affSColin Finck WSPSendTo(SOCKET Handle, 720c2c66affSColin Finck LPWSABUF lpBuffers, 721c2c66affSColin Finck DWORD dwBufferCount, 722c2c66affSColin Finck LPDWORD lpNumberOfBytesSent, 723c2c66affSColin Finck DWORD iFlags, 724c2c66affSColin Finck const struct sockaddr *SocketAddress, 725c2c66affSColin Finck int SocketAddressLength, 726c2c66affSColin Finck LPWSAOVERLAPPED lpOverlapped, 727c2c66affSColin Finck LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 728c2c66affSColin Finck LPWSATHREADID lpThreadId, 729c2c66affSColin Finck LPINT lpErrno) 730c2c66affSColin Finck { 731c2c66affSColin Finck PIO_STATUS_BLOCK IOSB; 732c2c66affSColin Finck IO_STATUS_BLOCK DummyIOSB; 733c2c66affSColin Finck AFD_SEND_INFO_UDP SendInfo; 734c2c66affSColin Finck NTSTATUS Status; 735c2c66affSColin Finck PVOID APCContext; 736c2c66affSColin Finck PVOID APCFunction; 737c2c66affSColin Finck HANDLE Event = NULL; 738c2c66affSColin Finck PTRANSPORT_ADDRESS RemoteAddress; 739c2c66affSColin Finck PSOCKADDR BindAddress = NULL; 740c2c66affSColin Finck INT BindAddressLength; 741c2c66affSColin Finck HANDLE SockEvent; 742c2c66affSColin Finck PSOCKET_INFORMATION Socket; 743c2c66affSColin Finck 744c2c66affSColin Finck /* Get the Socket Structure associate to this Socket */ 745c2c66affSColin Finck Socket = GetSocketStructure(Handle); 746c2c66affSColin Finck if (!Socket) 747c2c66affSColin Finck { 748c2c66affSColin Finck if (lpErrno) 749c2c66affSColin Finck *lpErrno = WSAENOTSOCK; 750c2c66affSColin Finck return SOCKET_ERROR; 751c2c66affSColin Finck } 752c2c66affSColin Finck if (!lpNumberOfBytesSent && !lpOverlapped) 753c2c66affSColin Finck { 754c2c66affSColin Finck if (lpErrno) 755c2c66affSColin Finck *lpErrno = WSAEFAULT; 756c2c66affSColin Finck return SOCKET_ERROR; 757c2c66affSColin Finck } 758c2c66affSColin Finck 759c2c66affSColin Finck if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS)) 760c2c66affSColin Finck { 761c2c66affSColin Finck /* Use WSPSend for connection-oriented sockets */ 762c2c66affSColin Finck return WSPSend(Handle, 763c2c66affSColin Finck lpBuffers, 764c2c66affSColin Finck dwBufferCount, 765c2c66affSColin Finck lpNumberOfBytesSent, 766c2c66affSColin Finck iFlags, 767c2c66affSColin Finck lpOverlapped, 768c2c66affSColin Finck lpCompletionRoutine, 769c2c66affSColin Finck lpThreadId, 770c2c66affSColin Finck lpErrno); 771c2c66affSColin Finck } 772c2c66affSColin Finck 773c2c66affSColin Finck /* Bind us First */ 774c2c66affSColin Finck if (Socket->SharedData->State == SocketOpen) 775c2c66affSColin Finck { 776c2c66affSColin Finck /* Get the Wildcard Address */ 777c2c66affSColin Finck BindAddressLength = Socket->HelperData->MaxWSAddressLength; 778c2c66affSColin Finck BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength); 779c2c66affSColin Finck if (!BindAddress) 780c2c66affSColin Finck { 781c2c66affSColin Finck MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 782c2c66affSColin Finck return INVALID_SOCKET; 783c2c66affSColin Finck } 784c2c66affSColin Finck 785c2c66affSColin Finck Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, 786c2c66affSColin Finck BindAddress, 787c2c66affSColin Finck &BindAddressLength); 788c2c66affSColin Finck /* Bind it */ 789c2c66affSColin Finck if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR) 790c2c66affSColin Finck return SOCKET_ERROR; 791c2c66affSColin Finck } 792c2c66affSColin Finck 793c2c66affSColin Finck RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength); 794c2c66affSColin Finck if (!RemoteAddress) 795c2c66affSColin Finck { 796c2c66affSColin Finck if (BindAddress != NULL) 797c2c66affSColin Finck { 798c2c66affSColin Finck HeapFree(GlobalHeap, 0, BindAddress); 799c2c66affSColin Finck } 800c2c66affSColin Finck return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 801c2c66affSColin Finck } 802c2c66affSColin Finck 803c2c66affSColin Finck Status = NtCreateEvent(&SockEvent, 804c2c66affSColin Finck EVENT_ALL_ACCESS, 805*bf5e3320SThomas Faber NULL, SynchronizationEvent, FALSE); 806c2c66affSColin Finck 807c2c66affSColin Finck if (!NT_SUCCESS(Status)) 808c2c66affSColin Finck { 809c2c66affSColin Finck HeapFree(GlobalHeap, 0, RemoteAddress); 810c2c66affSColin Finck if (BindAddress != NULL) 811c2c66affSColin Finck { 812c2c66affSColin Finck HeapFree(GlobalHeap, 0, BindAddress); 813c2c66affSColin Finck } 814c2c66affSColin Finck return SOCKET_ERROR; 815c2c66affSColin Finck } 816c2c66affSColin Finck 817c2c66affSColin Finck /* Set up Address in TDI Format */ 818c2c66affSColin Finck RemoteAddress->TAAddressCount = 1; 819c2c66affSColin Finck RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); 820c2c66affSColin Finck RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength); 821c2c66affSColin Finck 822c2c66affSColin Finck /* Set up Structure */ 823c2c66affSColin Finck SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; 824c2c66affSColin Finck SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; 825c2c66affSColin Finck SendInfo.BufferCount = dwBufferCount; 826c2c66affSColin Finck SendInfo.TdiConnection.RemoteAddress = RemoteAddress; 827c2c66affSColin Finck SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength; 828c2c66affSColin Finck 829c2c66affSColin Finck /* Verify if we should use APC */ 830c2c66affSColin Finck if (lpOverlapped == NULL) 831c2c66affSColin Finck { 832c2c66affSColin Finck /* Not using Overlapped structure, so use normal blocking on event */ 833c2c66affSColin Finck APCContext = NULL; 834c2c66affSColin Finck APCFunction = NULL; 835c2c66affSColin Finck Event = SockEvent; 836c2c66affSColin Finck IOSB = &DummyIOSB; 837c2c66affSColin Finck } 838c2c66affSColin Finck else 839c2c66affSColin Finck { 840c2c66affSColin Finck /* Overlapped request for non overlapped opened socket */ 841c2c66affSColin Finck if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 842c2c66affSColin Finck { 843c2c66affSColin Finck TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 844c2c66affSColin Finck return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); 845c2c66affSColin Finck } 846c2c66affSColin Finck if (lpCompletionRoutine == NULL) 847c2c66affSColin Finck { 848c2c66affSColin Finck /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ 849c2c66affSColin Finck APCContext = lpOverlapped; 850c2c66affSColin Finck APCFunction = NULL; 851c2c66affSColin Finck Event = lpOverlapped->hEvent; 852c2c66affSColin Finck } 853c2c66affSColin Finck else 854c2c66affSColin Finck { 855c2c66affSColin Finck /* Using Overlapped Structure and a Completion Routine, so use an APC */ 856c2c66affSColin Finck APCFunction = &AfdAPC; // should be a private io completion function inside us 857c2c66affSColin Finck APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 858c2c66affSColin Finck if (!APCContext) 859c2c66affSColin Finck { 860c2c66affSColin Finck ERR("Not enough memory for APC Context\n"); 861c2c66affSColin Finck return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent); 862c2c66affSColin Finck } 863c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; 864c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; 865c2c66affSColin Finck ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; 866c2c66affSColin Finck SendInfo.AfdFlags |= AFD_SKIP_FIO; 867c2c66affSColin Finck } 868c2c66affSColin Finck 869c2c66affSColin Finck IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; 870c2c66affSColin Finck SendInfo.AfdFlags |= AFD_OVERLAPPED; 871c2c66affSColin Finck } 872c2c66affSColin Finck 873c2c66affSColin Finck /* Send IOCTL */ 874c2c66affSColin Finck Status = NtDeviceIoControlFile((HANDLE)Handle, 875c2c66affSColin Finck Event, 876c2c66affSColin Finck APCFunction, 877c2c66affSColin Finck APCContext, 878c2c66affSColin Finck IOSB, 879c2c66affSColin Finck IOCTL_AFD_SEND_DATAGRAM, 880c2c66affSColin Finck &SendInfo, 881c2c66affSColin Finck sizeof(SendInfo), 882c2c66affSColin Finck NULL, 883c2c66affSColin Finck 0); 884c2c66affSColin Finck 885c2c66affSColin Finck /* Wait for completion of not overlapped */ 886c2c66affSColin Finck if (Status == STATUS_PENDING && lpOverlapped == NULL) 887c2c66affSColin Finck { 888c2c66affSColin Finck /* BUGBUG, shouldn't wait infinitely for send... */ 889c2c66affSColin Finck WaitForSingleObject(SockEvent, INFINITE); 890c2c66affSColin Finck Status = IOSB->Status; 891c2c66affSColin Finck } 892c2c66affSColin Finck 893c2c66affSColin Finck NtClose(SockEvent); 894c2c66affSColin Finck HeapFree(GlobalHeap, 0, RemoteAddress); 895c2c66affSColin Finck if (BindAddress != NULL) 896c2c66affSColin Finck { 897c2c66affSColin Finck HeapFree(GlobalHeap, 0, BindAddress); 898c2c66affSColin Finck } 899c2c66affSColin Finck 900c2c66affSColin Finck if (Status == STATUS_PENDING) 901c2c66affSColin Finck { 902c2c66affSColin Finck TRACE("Leaving (Pending)\n"); 903c2c66affSColin Finck return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); 904c2c66affSColin Finck } 905c2c66affSColin Finck 906c2c66affSColin Finck SockReenableAsyncSelectEvent(Socket, FD_WRITE); 907c2c66affSColin Finck 908c2c66affSColin Finck if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) 909c2c66affSColin Finck { 910c2c66affSColin Finck lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); 911c2c66affSColin Finck HeapFree(GlobalHeap, 0, (PVOID)APCContext); 912c2c66affSColin Finck } 913c2c66affSColin Finck 914c2c66affSColin Finck return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); 915c2c66affSColin Finck } 916c2c66affSColin Finck 917c2c66affSColin Finck INT 918c2c66affSColin Finck WSPAPI 919c2c66affSColin Finck WSPRecvDisconnect(IN SOCKET s, 920c2c66affSColin Finck OUT LPWSABUF lpInboundDisconnectData, 921c2c66affSColin Finck OUT LPINT lpErrno) 922c2c66affSColin Finck { 923c2c66affSColin Finck UNIMPLEMENTED; 924c2c66affSColin Finck return 0; 925c2c66affSColin Finck } 926c2c66affSColin Finck 927c2c66affSColin Finck 928c2c66affSColin Finck 929c2c66affSColin Finck INT 930c2c66affSColin Finck WSPAPI 931c2c66affSColin Finck WSPSendDisconnect(IN SOCKET s, 932c2c66affSColin Finck IN LPWSABUF lpOutboundDisconnectData, 933c2c66affSColin Finck OUT LPINT lpErrno) 934c2c66affSColin Finck { 935c2c66affSColin Finck UNIMPLEMENTED; 936c2c66affSColin Finck return 0; 937c2c66affSColin Finck } 938c2c66affSColin Finck 939c2c66affSColin Finck /* EOF */ 940