From e88f334ab29a2c514d0951d8ea18f414c3062406 Mon Sep 17 00:00:00 2001 From: Peter Hater <7element@mail.bg> Date: Tue, 24 Aug 2021 02:06:15 +0200 Subject: [PATCH] CORE-12152 --- dll/win32/msafd/misc/dllmain.c | 172 +++++++--- dll/win32/msafd/misc/sndrcv.c | 421 +++++++++++++++++-------- dll/win32/msafd/msafd.h | 35 +- drivers/network/afd/afd/tdi.c | 8 +- drivers/network/afd/afd/write.c | 12 +- sdk/lib/drivers/ip/transport/tcp/tcp.c | 8 +- 6 files changed, 459 insertions(+), 197 deletions(-) diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c index 7723b93d2367..6a5725595e00 100644 --- a/dll/win32/msafd/misc/dllmain.c +++ b/dll/win32/msafd/misc/dllmain.c @@ -418,7 +418,7 @@ WSPSocket(int AddressFamily, return (SOCKET)Sock; error: - ERR("Ending %x\n", Status); + TRACE("Ending %x\n", Status); if( SharedData ) { @@ -1821,6 +1821,55 @@ WSPAccept( return AcceptSocket; } +VOID +NTAPI +AfdConnectAPC(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved) +{ + PAFDCONNECTAPCCONTEXT Context = ApcContext; + + TRACE("AfdConnectAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information); + + if (Context->lpConnectInfo) + HeapFree(GlobalHeap, 0, Context->lpConnectInfo); + if (!Context->lpSocket) + { + HeapFree(GlobalHeap, 0, ApcContext); + return; + } + if (IoStatusBlock->Status == STATUS_SUCCESS) + { + Context->lpSocket->SharedData->ConnectTime = (GetTickCount() - Context->lpSocket->SharedData->ConnectTime) / 1000; + Context->lpSocket->SharedData->State = SocketConnected; + Context->lpSocket->TdiConnectionHandle = (HANDLE)IoStatusBlock->Information; + } + + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE); + + /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ + SockReenableAsyncSelectEvent(Context->lpSocket, FD_CONNECT); + + if (IoStatusBlock->Status == STATUS_SUCCESS && (Context->lpSocket->HelperEvents & WSH_NOTIFY_CONNECT)) + { + Context->lpSocket->HelperData->WSHNotify(Context->lpSocket->HelperContext, + Context->lpSocket->Handle, + Context->lpSocket->TdiAddressHandle, + Context->lpSocket->TdiConnectionHandle, + WSH_NOTIFY_CONNECT); + } + else if (IoStatusBlock->Status != STATUS_SUCCESS && (Context->lpSocket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR)) + { + Context->lpSocket->HelperData->WSHNotify(Context->lpSocket->HelperContext, + Context->lpSocket->Handle, + Context->lpSocket->TdiAddressHandle, + Context->lpSocket->TdiConnectionHandle, + WSH_NOTIFY_CONNECT_ERROR); + } + HeapFree(GlobalHeap, 0, ApcContext); +} + int WSPAPI WSPConnect(SOCKET Handle, @@ -1832,7 +1881,8 @@ WSPConnect(SOCKET Handle, LPQOS lpGQOS, LPINT lpErrno) { - IO_STATUS_BLOCK IOSB; + IO_STATUS_BLOCK DummyIOSB; + PIO_STATUS_BLOCK IOSB = &DummyIOSB; PAFD_CONNECT_INFO ConnectInfo = NULL; PSOCKET_INFORMATION Socket; NTSTATUS Status; @@ -1843,8 +1893,10 @@ WSPConnect(SOCKET Handle, PSOCKADDR BindAddress; HANDLE SockEvent; int SocketDataLength; + PAFDCONNECTAPCCONTEXT APCContext = NULL; + PIO_APC_ROUTINE APCFunction = NULL; - TRACE("Called (%lx) %lx:%d\n", Handle, ((const struct sockaddr_in *)SocketAddress)->sin_addr, ((const struct sockaddr_in *)SocketAddress)->sin_port); + TRACE("WSPConnect (%lx)\n", Handle); /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); @@ -1890,7 +1942,7 @@ WSPConnect(SOCKET Handle, SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA, lpCallerData->buf, ConnectDataLength, @@ -1900,7 +1952,7 @@ WSPConnect(SOCKET Handle, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1911,7 +1963,7 @@ WSPConnect(SOCKET Handle, SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data); /* Allocate a connection info buffer with SocketDataLength bytes of payload */ - ConnectInfo = HeapAlloc(GetProcessHeap(), 0, + ConnectInfo = HeapAlloc(GlobalHeap, 0, FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress.Address[0].Address[SocketDataLength])); if (!ConnectInfo) @@ -1934,7 +1986,7 @@ WSPConnect(SOCKET Handle, * at the end of this function right after the Async Thread disables it. * This should only happen at the *next* WSPConnect */ - if (Socket->SharedData->AsyncEvents & FD_CONNECT) + if ((Socket->SharedData->AsyncEvents & FD_CONNECT) != 0) { Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; } @@ -1947,7 +1999,7 @@ WSPConnect(SOCKET Handle, SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA_SIZE, &InConnectDataLength, sizeof(InConnectDataLength), @@ -1958,7 +2010,7 @@ WSPConnect(SOCKET Handle, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1970,18 +2022,28 @@ WSPConnect(SOCKET Handle, ConnectInfo->UseSAN = FALSE; ConnectInfo->Unknown = 0; - /* FIXME: Handle Async Connect */ if (Socket->SharedData->NonBlocking) { - ERR("Async Connect UNIMPLEMENTED!\n"); + APCFunction = &AfdConnectAPC; // should be a private io completition function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDCONNECTAPCCONTEXT)); + if (!APCContext) + { + ERR("Not enough memory for APC Context\n"); + return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); + } + APCContext->lpConnectInfo = ConnectInfo; + APCContext->lpSocket = Socket; + IOSB = &APCContext->IoStatusBlock; } + IOSB->Status = STATUS_PENDING; + /* Send IOCTL */ Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, + APCFunction != NULL ? NULL : SockEvent, + APCFunction, + APCContext, + IOSB, IOCTL_AFD_CONNECT, ConnectInfo, 0x22, @@ -1990,16 +2052,33 @@ WSPConnect(SOCKET Handle, /* Wait for return */ if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + WaitForSingleObject(SockEvent, Socket->SharedData->NonBlocking ? 0 : INFINITE); + Status = IOSB->Status; + } + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) + { + NtClose(SockEvent); + if (Socket->SharedData->NonBlocking) + Status = STATUS_CANT_WAIT; + TRACE("Leaving (Pending)\n"); + return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); } + if (APCFunction) + { + APCContext->lpConnectInfo = NULL; + APCContext->lpSocket = NULL; + /* This will be freed by the APC */ + //HeapFree(GlobalHeap, 0, APCContext); + } + if (ConnectInfo) HeapFree(GlobalHeap, 0, ConnectInfo); + Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); if (Status != STATUS_SUCCESS) goto notify; Socket->SharedData->State = SocketConnected; - Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; + Socket->TdiConnectionHandle = (HANDLE)IOSB->Information; Socket->SharedData->ConnectTime = GetCurrentTimeInSeconds(); /* Get any pending connect data */ @@ -2009,7 +2088,7 @@ WSPConnect(SOCKET Handle, SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_GET_CONNECT_DATA, NULL, 0, @@ -2019,14 +2098,12 @@ WSPConnect(SOCKET Handle, if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } } - TRACE("Ending %lx\n", IOSB.Status); - notify: - if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo); + TRACE("Ending %lx\n", IOSB->Status); /* Re-enable Async Event */ SockReenableAsyncSelectEvent(Socket, FD_WRITE); @@ -3062,6 +3139,9 @@ WSPAddressToString(IN LPSOCKADDR lpsaAddress, WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */ WCHAR *p; + /* Allow for APC to be processed */ + SleepEx(0, TRUE); + if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength) { if (lpErrno) *lpErrno = WSAEFAULT; @@ -3251,9 +3331,10 @@ AfdInfoAPC(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved) { - PAFDAPCCONTEXT Context = ApcContext; + PAFDINFOAPCCONTEXT Context = ApcContext; - Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + if (Context->lpCompletionRoutine) + Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); HeapFree(GlobalHeap, 0, ApcContext); } @@ -3270,7 +3351,7 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3303,12 +3384,12 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); NtClose( SockEvent ); - return 0; + return MsafdReturnWithErrno(STATUS_SUCCESS, NULL, 0, NULL); } if (CompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = (PAFDAPCCONTEXT)Overlapped; + APCContext = (PAFDINFOAPCCONTEXT)Overlapped; APCFunction = NULL; Event = Overlapped->hEvent; } @@ -3316,16 +3397,15 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, { /* Using Overlapped Structure and a Completition Routine, so use an APC */ APCFunction = &AfdInfoAPC; // should be a private io completition function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDINFOAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); NtClose( SockEvent ); - return WSAEFAULT; + return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, NULL, 0, NULL); } APCContext->lpCompletionRoutine = CompletionRoutine; APCContext->lpOverlapped = Overlapped; - APCContext->lpSocket = Socket; } IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal; @@ -3346,9 +3426,9 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, sizeof(InfoData)); /* Wait for return */ - if (Status == STATUS_PENDING && Overlapped == NULL) + if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); + WaitForSingleObject(SockEvent, Overlapped != NULL ? 0 : INFINITE); Status = IOSB->Status; } @@ -3359,11 +3439,11 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, if (Status == STATUS_PENDING) { TRACE("Leaving (Pending)\n"); - return WSA_IO_PENDING; + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } if (Status != STATUS_SUCCESS) - return SOCKET_ERROR; + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); /* Return Information */ if (Ulong != NULL) @@ -3379,8 +3459,7 @@ GetSocketInformation(PSOCKET_INFORMATION Socket, *Boolean = InfoData.Information.Boolean; } - return NO_ERROR; - + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } @@ -3397,7 +3476,7 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3444,12 +3523,12 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); NtClose( SockEvent ); - return 0; + return MsafdReturnWithErrno(STATUS_SUCCESS, NULL, 0, NULL); } if (CompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = (PAFDAPCCONTEXT)Overlapped; + APCContext = (PAFDINFOAPCCONTEXT)Overlapped; APCFunction = NULL; Event = Overlapped->hEvent; } @@ -3457,16 +3536,15 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, { /* Using Overlapped Structure and a Completition Routine, so use an APC */ APCFunction = &AfdInfoAPC; // should be a private io completition function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDINFOAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); NtClose( SockEvent ); - return WSAEFAULT; + return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, NULL, 0, NULL); } APCContext->lpCompletionRoutine = CompletionRoutine; APCContext->lpOverlapped = Overlapped; - APCContext->lpSocket = Socket; } IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal; @@ -3487,9 +3565,9 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, 0); /* Wait for return */ - if (Status == STATUS_PENDING && Overlapped == NULL) + if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); + WaitForSingleObject(SockEvent, Overlapped != NULL ? 0 : INFINITE); Status = IOSB->Status; } @@ -3500,10 +3578,10 @@ SetSocketInformation(PSOCKET_INFORMATION Socket, if (Status == STATUS_PENDING) { TRACE("Leaving (Pending)\n"); - return WSA_IO_PENDING; + //return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } - return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR; + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } diff --git a/dll/win32/msafd/misc/sndrcv.c b/dll/win32/msafd/misc/sndrcv.c index 07fe8b1f1c02..2839a8273bb5 100644 --- a/dll/win32/msafd/misc/sndrcv.c +++ b/dll/win32/msafd/misc/sndrcv.c @@ -137,18 +137,48 @@ WSPGetOverlappedResult( VOID NTAPI -AfdAPC(PVOID ApcContext, +AfdRecvAPC(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved) { - PAFDAPCCONTEXT Context = ApcContext; + PAFDRECVAPCCONTEXT Context = ApcContext; - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB); - SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ); - SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE); + TRACE("AfdRecvAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information); + if (Context->lpSocket && Context->lpSocket->SharedData) + { + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Context->lpSocket, FD_OOB); + SockReenableAsyncSelectEvent(Context->lpSocket, FD_READ); + } + + if (Context->lpCompletionRoutine) + Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + if (Context->lpRecvInfo) + HeapFree(GlobalHeap, 0, Context->lpRecvInfo); + HeapFree(GlobalHeap, 0, ApcContext); +} + +VOID +NTAPI +AfdSendAPC(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved) +{ + PAFDSENDAPCCONTEXT Context = ApcContext; + + TRACE("AfdSendAPC %p %lx %lx\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information); + if (Context->lpSocket && Context->lpSocket->SharedData) + { + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Context->lpSocket, FD_WRITE); + } - Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + if (Context->lpCompletionRoutine) + Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + if (Context->lpSendInfo) + HeapFree(GlobalHeap, 0, Context->lpSendInfo); + if (Context->lpRemoteAddress) + HeapFree(GlobalHeap, 0, Context->lpRemoteAddress); HeapFree(GlobalHeap, 0, ApcContext); } @@ -166,9 +196,9 @@ WSPRecv(SOCKET Handle, { PIO_STATUS_BLOCK IOSB; IO_STATUS_BLOCK DummyIOSB; - AFD_RECV_INFO RecvInfo; + PAFD_RECV_INFO RecvInfo; NTSTATUS Status; - PVOID APCContext; + PAFDRECVAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -197,38 +227,50 @@ WSPRecv(SOCKET Handle, return SOCKET_ERROR; } + /* Allocate a recv info buffer */ + RecvInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_RECV_INFO)); + if (!RecvInfo) + { + if (lpErrno) + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); - if( !NT_SUCCESS(Status) ) - return -1; + if (!NT_SUCCESS(Status)) + { + HeapFree(GlobalHeap, 0, RecvInfo); + return SOCKET_ERROR; + } /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; + RecvInfo->BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo->BufferCount = dwBufferCount; + RecvInfo->TdiFlags = 0; + RecvInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; /* Set the TDI Flags */ - if (*ReceiveFlags == 0) + if (!ReceiveFlags || *ReceiveFlags == 0) { - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + RecvInfo->TdiFlags |= TDI_RECEIVE_NORMAL; } else { if (*ReceiveFlags & MSG_OOB) { - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + RecvInfo->TdiFlags |= TDI_RECEIVE_EXPEDITED; } if (*ReceiveFlags & MSG_PEEK) { - RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + RecvInfo->TdiFlags |= TDI_RECEIVE_PEEK; } if (*ReceiveFlags & MSG_PARTIAL) { - RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + RecvInfo->TdiFlags |= TDI_RECEIVE_PARTIAL; } } @@ -248,35 +290,37 @@ WSPRecv(SOCKET Handle, if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); + return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead); } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ - APCContext = lpOverlapped; + APCContext = (PAFDRECVAPCCONTEXT)lpOverlapped; APCFunction = NULL; Event = lpOverlapped->hEvent; } else { /* Using Overlapped Structure and a Completion Routine, so use an APC */ - APCFunction = &AfdAPC; // should be a private io completion function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCFunction = &AfdRecvAPC; // should be a private io completion function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDRECVAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead); } - ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; - ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; - ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; - RecvInfo.AfdFlags |= AFD_SKIP_FIO; + APCContext->lpCompletionRoutine = lpCompletionRoutine; + APCContext->lpOverlapped = lpOverlapped; + APCContext->lpSocket = Socket; + APCContext->lpRecvInfo = RecvInfo; + RecvInfo->AfdFlags |= AFD_SKIP_FIO; } IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - RecvInfo.AfdFlags |= AFD_OVERLAPPED; + RecvInfo->AfdFlags |= AFD_OVERLAPPED; } + IOSB->Information = 0; IOSB->Status = STATUS_PENDING; /* Send IOCTL */ @@ -286,36 +330,46 @@ WSPRecv(SOCKET Handle, APCContext, IOSB, IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), + RecvInfo, + sizeof(AFD_RECV_INFO), NULL, 0); /* Wait for completion of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) + if (Status == STATUS_PENDING) { /* It's up to the protocol to time out recv. We must wait * until the protocol decides it's had enough. */ - WaitForSingleObject(SockEvent, INFINITE); + WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); Status = IOSB->Status; } NtClose( SockEvent ); - TRACE("Status %x Information %d\n", Status, IOSB->Information); - if (Status == STATUS_PENDING) { TRACE("Leaving (Pending)\n"); return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); } - /* Return the Flags */ - *ReceiveFlags = 0; + if (APCFunction) + { + APCContext->lpRecvInfo = NULL; + APCContext->lpCompletionRoutine = NULL; + APCContext->lpSocket = NULL; + /* This will be freed by the APC */ + //HeapFree(GlobalHeap, 0, APCContext); + } + HeapFree(GlobalHeap, 0, RecvInfo); - switch (Status) + /* Return the Flags */ + if (ReceiveFlags) { + *ReceiveFlags = 0; + + switch (Status) + { case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; break; @@ -325,22 +379,27 @@ WSPRecv(SOCKET Handle, case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; + } } - /* Re-enable Async Event */ - if (*ReceiveFlags & MSG_OOB) + if (Status == STATUS_SUCCESS) { - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - SockReenableAsyncSelectEvent(Socket, FD_READ); + /* Re-enable Async Event */ + if (ReceiveFlags && *ReceiveFlags & MSG_OOB) + { + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + SockReenableAsyncSelectEvent(Socket, FD_READ); + } } + TRACE("Leaving (Success, %ld %ld)\n", Status, IOSB->Information); + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) { - lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); - HeapFree(GlobalHeap, 0, (PVOID)APCContext); + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, ReceiveFlags != NULL ? *ReceiveFlags : 0); } return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); @@ -362,14 +421,16 @@ WSPRecvFrom(SOCKET Handle, { PIO_STATUS_BLOCK IOSB; IO_STATUS_BLOCK DummyIOSB; - AFD_RECV_INFO_UDP RecvInfo; + PAFD_RECV_INFO_UDP RecvInfo; NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; + PAFDRECVAPCCONTEXT APCContext; + PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; PSOCKET_INFORMATION Socket; + TRACE("WSPRecvFrom Called (%x)\n", Handle); + /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); if (!Socket) @@ -416,40 +477,52 @@ WSPRecvFrom(SOCKET Handle, return SOCKET_ERROR; } + /* Allocate a recv info buffer */ + RecvInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_RECV_INFO_UDP)); + if (!RecvInfo) + { + if (lpErrno) + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); if( !NT_SUCCESS(Status) ) - return -1; + { + HeapFree(GlobalHeap, 0, RecvInfo); + return SOCKET_ERROR; + } /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; - RecvInfo.AddressLength = SocketAddressLength; - RecvInfo.Address = SocketAddress; + RecvInfo->BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo->BufferCount = dwBufferCount; + RecvInfo->TdiFlags = 0; + RecvInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; + RecvInfo->AddressLength = SocketAddressLength; + RecvInfo->Address = SocketAddress; /* Set the TDI Flags */ - if (*ReceiveFlags == 0) + if (!ReceiveFlags || *ReceiveFlags == 0) { - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + RecvInfo->TdiFlags |= TDI_RECEIVE_NORMAL; } else { if (*ReceiveFlags & MSG_OOB) { - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + RecvInfo->TdiFlags |= TDI_RECEIVE_EXPEDITED; } if (*ReceiveFlags & MSG_PEEK) { - RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + RecvInfo->TdiFlags |= TDI_RECEIVE_PEEK; } if (*ReceiveFlags & MSG_PARTIAL) { - RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + RecvInfo->TdiFlags |= TDI_RECEIVE_PARTIAL; } } @@ -469,35 +542,37 @@ WSPRecvFrom(SOCKET Handle, if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead); + return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead); } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ - APCContext = lpOverlapped; + APCContext = (PAFDRECVAPCCONTEXT)lpOverlapped; APCFunction = NULL; Event = lpOverlapped->hEvent; } else { /* Using Overlapped Structure and a Completion Routine, so use an APC */ - APCFunction = &AfdAPC; // should be a private io completion function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCFunction = &AfdRecvAPC; // should be a private io completion function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDRECVAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead); } - ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; - ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; - ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; - RecvInfo.AfdFlags |= AFD_SKIP_FIO; + APCContext->lpCompletionRoutine = lpCompletionRoutine; + APCContext->lpOverlapped = lpOverlapped; + APCContext->lpSocket = Socket; + APCContext->lpRecvInfo = RecvInfo; + RecvInfo->AfdFlags |= AFD_SKIP_FIO; } IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - RecvInfo.AfdFlags |= AFD_OVERLAPPED; + RecvInfo->AfdFlags |= AFD_OVERLAPPED; } + IOSB->Information = 0; IOSB->Status = STATUS_PENDING; /* Send IOCTL */ @@ -507,15 +582,15 @@ WSPRecvFrom(SOCKET Handle, APCContext, IOSB, IOCTL_AFD_RECV_DATAGRAM, - &RecvInfo, - sizeof(RecvInfo), + RecvInfo, + sizeof(AFD_RECV_INFO_UDP), NULL, 0); /* Wait for completion of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) + if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive... + WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); // BUGBUG, shouldn wait infintely for receive... Status = IOSB->Status; } @@ -527,11 +602,23 @@ WSPRecvFrom(SOCKET Handle, return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); } - /* Return the Flags */ - *ReceiveFlags = 0; + if (APCFunction) + { + APCContext->lpRecvInfo = NULL; + APCContext->lpCompletionRoutine = NULL; + APCContext->lpSocket = NULL; + /* This will be freed by the APC */ + //HeapFree(GlobalHeap, 0, APCContext); + } + HeapFree(GlobalHeap, 0, RecvInfo); - switch (Status) + if (ReceiveFlags) { + /* Return the Flags */ + *ReceiveFlags = 0; + + switch (Status) + { case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; break; @@ -541,22 +628,27 @@ WSPRecvFrom(SOCKET Handle, case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; + } } - /* Re-enable Async Event */ - if (*ReceiveFlags & MSG_OOB) + if (Status == STATUS_SUCCESS) { - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - SockReenableAsyncSelectEvent(Socket, FD_READ); + /* Re-enable Async Event */ + if (ReceiveFlags && *ReceiveFlags & MSG_OOB) + { + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + SockReenableAsyncSelectEvent(Socket, FD_READ); + } } + TRACE("Leaving (Success, %ld %ld)\n", Status, IOSB->Information); + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) { - lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags); - HeapFree(GlobalHeap, 0, (PVOID)APCContext); + lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, ReceiveFlags != NULL ? *ReceiveFlags : 0); } return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); @@ -577,14 +669,16 @@ WSPSend(SOCKET Handle, { PIO_STATUS_BLOCK IOSB; IO_STATUS_BLOCK DummyIOSB; - AFD_SEND_INFO SendInfo; + PAFD_SEND_INFO SendInfo; NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; + PAFDSENDAPCCONTEXT APCContext; + PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; PSOCKET_INFORMATION Socket; + TRACE("WSPSend Called (%x)\n", Handle); + /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); if (!Socket) @@ -600,30 +694,40 @@ WSPSend(SOCKET Handle, return SOCKET_ERROR; } + /* Allocate a send info buffer */ + SendInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_SEND_INFO)); + if (!SendInfo) + { + if (lpErrno) + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); if( !NT_SUCCESS(Status) ) - return -1; - - TRACE("Called\n"); + { + HeapFree(GlobalHeap, 0, SendInfo); + return SOCKET_ERROR; + } /* Set up the Send Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiFlags = 0; - SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; + SendInfo->BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo->BufferCount = dwBufferCount; + SendInfo->TdiFlags = 0; + SendInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; /* Set the TDI Flags */ if (iFlags) { if (iFlags & MSG_OOB) { - SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; + SendInfo->TdiFlags |= TDI_SEND_EXPEDITED; } if (iFlags & MSG_PARTIAL) { - SendInfo.TdiFlags |= TDI_SEND_PARTIAL; + SendInfo->TdiFlags |= TDI_SEND_PARTIAL; } } @@ -642,35 +746,38 @@ WSPSend(SOCKET Handle, if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); + return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent); } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ - APCContext = lpOverlapped; + APCContext = (PAFDSENDAPCCONTEXT)lpOverlapped; APCFunction = NULL; Event = lpOverlapped->hEvent; } else { /* Using Overlapped Structure and a Completion Routine, so use an APC */ - APCFunction = &AfdAPC; // should be a private io completion function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCFunction = &AfdSendAPC; // should be a private io completion function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDSENDAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent); } - ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; - ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; - ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; - SendInfo.AfdFlags |= AFD_SKIP_FIO; + APCContext->lpCompletionRoutine = lpCompletionRoutine; + APCContext->lpOverlapped = lpOverlapped; + APCContext->lpSocket = Socket; + APCContext->lpSendInfo = SendInfo; + APCContext->lpRemoteAddress = NULL; + SendInfo->AfdFlags |= AFD_SKIP_FIO; } IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - SendInfo.AfdFlags |= AFD_OVERLAPPED; + SendInfo->AfdFlags |= AFD_OVERLAPPED; } + IOSB->Information = 0; IOSB->Status = STATUS_PENDING; /* Send IOCTL */ @@ -680,15 +787,15 @@ WSPSend(SOCKET Handle, APCContext, IOSB, IOCTL_AFD_SEND, - &SendInfo, - sizeof(SendInfo), + SendInfo, + sizeof(AFD_SEND_INFO), NULL, 0); /* Wait for completion of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) + if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send... + WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); // BUGBUG, shouldn wait infintely for send... Status = IOSB->Status; } @@ -700,15 +807,24 @@ WSPSend(SOCKET Handle, return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); } + if (APCFunction) + { + APCContext->lpSendInfo = NULL; + APCContext->lpCompletionRoutine = NULL; + APCContext->lpSocket = NULL; + /* This will be freed by the APC */ + //HeapFree(GlobalHeap, 0, APCContext); + } + HeapFree(GlobalHeap, 0, SendInfo); + /* Re-enable Async Event */ SockReenableAsyncSelectEvent(Socket, FD_WRITE); - TRACE("Leaving (Success, %d)\n", IOSB->Information); + TRACE("Leaving (%ld %ld)\n", Status, IOSB->Information); if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) { lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); - HeapFree(GlobalHeap, 0, (PVOID)APCContext); } return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent ); @@ -730,10 +846,10 @@ WSPSendTo(SOCKET Handle, { PIO_STATUS_BLOCK IOSB; IO_STATUS_BLOCK DummyIOSB; - AFD_SEND_INFO_UDP SendInfo; + PAFD_SEND_INFO_UDP SendInfo; NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; + PAFDSENDAPCCONTEXT APCContext; + PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; PTRANSPORT_ADDRESS RemoteAddress; PSOCKADDR BindAddress = NULL; @@ -741,6 +857,8 @@ WSPSendTo(SOCKET Handle, HANDLE SockEvent; PSOCKET_INFORMATION Socket; + TRACE("WSPSendTo Called (%x)\n", Handle); + /* Get the Socket Structure associate to this Socket */ Socket = GetSocketStructure(Handle); if (!Socket) @@ -800,12 +918,24 @@ WSPSendTo(SOCKET Handle, return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); } + SendInfo = HeapAlloc(GlobalHeap, 0, sizeof(AFD_SEND_INFO_UDP)); + if (!SendInfo) + { + HeapFree(GlobalHeap, 0, RemoteAddress); + if (BindAddress != NULL) + { + HeapFree(GlobalHeap, 0, BindAddress); + } + return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); + } + Status = NtCreateEvent(&SockEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { + HeapFree(GlobalHeap, 0, SendInfo); HeapFree(GlobalHeap, 0, RemoteAddress); if (BindAddress != NULL) { @@ -820,11 +950,11 @@ WSPSendTo(SOCKET Handle, RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength); /* Set up Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiConnection.RemoteAddress = RemoteAddress; - SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength; + SendInfo->BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo->AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0; + SendInfo->BufferCount = dwBufferCount; + SendInfo->TdiConnection.RemoteAddress = RemoteAddress; + SendInfo->TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength; /* Verify if we should use APC */ if (lpOverlapped == NULL) @@ -841,35 +971,40 @@ WSPSendTo(SOCKET Handle, if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent); + return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent); } if (lpCompletionRoutine == NULL) { /* Using Overlapped Structure, but no Completion Routine, so no need for APC */ - APCContext = lpOverlapped; + APCContext = (PAFDSENDAPCCONTEXT)lpOverlapped; APCFunction = NULL; Event = lpOverlapped->hEvent; } else { /* Using Overlapped Structure and a Completion Routine, so use an APC */ - APCFunction = &AfdAPC; // should be a private io completion function inside us - APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); + APCFunction = &AfdSendAPC; // should be a private io completion function inside us + APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDSENDAPCCONTEXT)); if (!APCContext) { ERR("Not enough memory for APC Context\n"); return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent); } - ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine; - ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped; - ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket; - SendInfo.AfdFlags |= AFD_SKIP_FIO; + APCContext->lpCompletionRoutine = lpCompletionRoutine; + APCContext->lpOverlapped = lpOverlapped; + APCContext->lpSocket = Socket; + APCContext->lpSendInfo = SendInfo; + APCContext->lpRemoteAddress = RemoteAddress; + SendInfo->AfdFlags |= AFD_SKIP_FIO; } IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - SendInfo.AfdFlags |= AFD_OVERLAPPED; + SendInfo->AfdFlags |= AFD_OVERLAPPED; } + IOSB->Information = 0; + IOSB->Status = STATUS_PENDING; + /* Send IOCTL */ Status = NtDeviceIoControlFile((HANDLE)Handle, Event, @@ -877,21 +1012,21 @@ WSPSendTo(SOCKET Handle, APCContext, IOSB, IOCTL_AFD_SEND_DATAGRAM, - &SendInfo, - sizeof(SendInfo), + SendInfo, + sizeof(AFD_SEND_INFO_UDP), NULL, 0); /* Wait for completion of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) + if (Status == STATUS_PENDING) { /* BUGBUG, shouldn't wait infinitely for send... */ - WaitForSingleObject(SockEvent, INFINITE); + WaitForSingleObject(SockEvent, (lpOverlapped || Socket->SharedData->NonBlocking) ? 0 : INFINITE); Status = IOSB->Status; } NtClose(SockEvent); - HeapFree(GlobalHeap, 0, RemoteAddress); + if (BindAddress != NULL) { HeapFree(GlobalHeap, 0, BindAddress); @@ -902,13 +1037,25 @@ WSPSendTo(SOCKET Handle, TRACE("Leaving (Pending)\n"); return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); } + if (APCFunction) + { + APCContext->lpSendInfo = NULL; + APCContext->lpRemoteAddress = NULL; + APCContext->lpCompletionRoutine = NULL; + APCContext->lpSocket = NULL; + /* This will be freed by the APC */ + //HeapFree(GlobalHeap, 0, APCContext); + } + HeapFree(GlobalHeap, 0, SendInfo); + HeapFree(GlobalHeap, 0, RemoteAddress); SockReenableAsyncSelectEvent(Socket, FD_WRITE); + TRACE("Leaving (%ld %ld)\n", Status, IOSB->Information); + if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine) { lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0); - HeapFree(GlobalHeap, 0, (PVOID)APCContext); } return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); diff --git a/dll/win32/msafd/msafd.h b/dll/win32/msafd/msafd.h index 87b0125cc4c6..0b3531aac24e 100644 --- a/dll/win32/msafd/msafd.h +++ b/dll/win32/msafd/msafd.h @@ -133,12 +133,38 @@ typedef struct _ASYNC_DATA { AFD_POLL_INFO AsyncSelectInfo; } ASYNC_DATA, *PASYNC_DATA; -typedef struct _AFDAPCCONTEXT +typedef struct _AFDINFOAPCCONTEXT +{ + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; +} AFDINFOAPCCONTEXT, *PAFDINFOAPCCONTEXT; + +typedef struct _AFDSENDAPCCONTEXT { LPWSAOVERLAPPED lpOverlapped; LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; PSOCKET_INFORMATION lpSocket; -} AFDAPCCONTEXT, *PAFDAPCCONTEXT; + IO_STATUS_BLOCK IoStatusBlock; + LPVOID lpSendInfo; + PTRANSPORT_ADDRESS lpRemoteAddress; +} AFDSENDAPCCONTEXT, *PAFDSENDAPCCONTEXT; + +typedef struct _AFDRECVAPCCONTEXT +{ + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; + PSOCKET_INFORMATION lpSocket; + IO_STATUS_BLOCK IoStatusBlock; + LPVOID lpRecvInfo; +} AFDRECVAPCCONTEXT, *PAFDRECVAPCCONTEXT; + +typedef struct _AFDCONNECTAPCCONTEXT +{ + PAFD_CONNECT_INFO lpConnectInfo; + PSOCKET_INFORMATION lpSocket; + IO_STATUS_BLOCK IoStatusBlock; +} AFDCONNECTAPCCONTEXT, *PAFDCONNECTAPCCONTEXT; + _Must_inspect_result_ SOCKET @@ -548,6 +574,9 @@ MsafdReturnWithErrno(NTSTATUS Status, DWORD Received, LPDWORD ReturnedBytes) { + /* Allow for APC to be processed */ + SleepEx(0, TRUE); + if (Errno) { *Errno = TranslateNtStatusError(Status); @@ -559,7 +588,7 @@ MsafdReturnWithErrno(NTSTATUS Status, } else { - DbgPrint("%s: Received invalid lpErrno pointer!\n", __FUNCTION__); + //DbgPrint("%s: Received invalid lpErrno pointer!\n", __FUNCTION__); if (ReturnedBytes) *ReturnedBytes = (Status == STATUS_SUCCESS) ? Received : 0; diff --git a/drivers/network/afd/afd/tdi.c b/drivers/network/afd/afd/tdi.c index 75085bcc2230..84e4384edccc 100644 --- a/drivers/network/afd/afd/tdi.c +++ b/drivers/network/afd/afd/tdi.c @@ -966,11 +966,9 @@ NTSTATUS TdiSend( Flags, /* Flags */ BufferLength); /* Length of data */ - TdiCall(*Irp, DeviceObject, NULL, NULL); /* Does not block... The MDL is deleted in the receive completion routine. */ - - return STATUS_PENDING; + return TdiCall(*Irp, DeviceObject, NULL, NULL); } NTSTATUS TdiReceive( @@ -1239,11 +1237,9 @@ NTSTATUS TdiSendDatagram( BufferLength, /* Bytes to send */ Addr); /* Address */ - TdiCall(*Irp, DeviceObject, NULL, NULL); /* Does not block... The MDL is deleted in the send completion routine. */ - - return STATUS_PENDING; + return TdiCall(*Irp, DeviceObject, NULL, NULL); } NTSTATUS TdiDisconnect( diff --git a/drivers/network/afd/afd/write.c b/drivers/network/afd/afd/write.c index 29ad9501b73b..f7cd38c6e523 100644 --- a/drivers/network/afd/afd/write.c +++ b/drivers/network/afd/afd/write.c @@ -379,6 +379,10 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { + if (SendReq->BufferCount > 1) + { + AFD_DbgPrint(MIN_TRACE,("WARN: More than one buffer %ld!\n", SendReq->BufferCount)); + } Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, @@ -390,7 +394,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, { NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; + Irp->IoStatus.Information = Status == STATUS_SUCCESS ? SendReq->BufferArray[0].len : 0; (void)IoSetCancelRoutine(Irp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); @@ -645,6 +649,10 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { + if (SendReq->BufferCount > 1) + { + AFD_DbgPrint(MIN_TRACE,("WARN: More than one buffer %ld!\n", SendReq->BufferCount)); + } Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, @@ -656,7 +664,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, { NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; + Irp->IoStatus.Information = Status == STATUS_SUCCESS ? SendReq->BufferArray[0].len : 0; (void)IoSetCancelRoutine(Irp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); diff --git a/sdk/lib/drivers/ip/transport/tcp/tcp.c b/sdk/lib/drivers/ip/transport/tcp/tcp.c index 7bdc8ab7486a..8ed1d8844b39 100644 --- a/sdk/lib/drivers/ip/transport/tcp/tcp.c +++ b/sdk/lib/drivers/ip/transport/tcp/tcp.c @@ -365,8 +365,12 @@ NTSTATUS TCPConnect return Status; } - /* Copy bind address into connection */ - Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr; + /* Check if we had an unspecified address */ + if (Connection->AddressFile->Address.Address.IPv4Address != bindaddr.addr) + { + /* We did, so we need to copy back the address */ + Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr; + } /* Check if we had an unspecified port */ if (!Connection->AddressFile->Port) {