Index: dll/win32/msafd/misc/dllmain.c =================================================================== --- dll/win32/msafd/misc/dllmain.c (revision 73320) +++ dll/win32/msafd/misc/dllmain.c (working copy) @@ -402,7 +402,7 @@ return (SOCKET)Sock; error: - ERR("Ending %x\n", Status); + TRACE("Ending %x\n", Status); if( SharedData ) { @@ -1778,6 +1778,55 @@ 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, @@ -1789,7 +1838,8 @@ 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; @@ -1800,8 +1850,10 @@ 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); @@ -1847,7 +1899,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA, lpCallerData->buf, ConnectDataLength, @@ -1857,7 +1909,7 @@ if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1868,7 +1920,7 @@ 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) @@ -1891,7 +1943,7 @@ * 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; } @@ -1904,7 +1956,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA_SIZE, &InConnectDataLength, sizeof(InConnectDataLength), @@ -1915,7 +1967,7 @@ if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1927,18 +1979,28 @@ 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, @@ -1947,16 +2009,33 @@ /* 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 */ @@ -1966,7 +2045,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_GET_CONNECT_DATA, NULL, 0, @@ -1976,14 +2055,12 @@ 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); @@ -2923,6 +3000,9 @@ 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; @@ -3112,9 +3192,10 @@ 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); } @@ -3131,7 +3212,7 @@ IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3163,12 +3244,12 @@ if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - 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; } @@ -3176,15 +3257,14 @@ { /* 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"); - 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; @@ -3205,22 +3285,24 @@ 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; } TRACE("Status %x Information %d\n", Status, IOSB->Information); + NtClose( SockEvent ); + 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) @@ -3236,10 +3318,7 @@ *Boolean = InfoData.Information.Boolean; } - NtClose( SockEvent ); - - return NO_ERROR; - + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } @@ -3256,7 +3335,7 @@ IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3302,12 +3381,12 @@ if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) { TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); - 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; } @@ -3315,15 +3394,14 @@ { /* 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"); - 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; @@ -3344,9 +3422,9 @@ 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; } @@ -3357,10 +3435,10 @@ 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); } Index: dll/win32/msafd/misc/event.c =================================================================== --- dll/win32/msafd/misc/event.c (revision 73320) +++ dll/win32/msafd/misc/event.c (working copy) @@ -192,7 +192,7 @@ if (Status != STATUS_SUCCESS) { - ERR("Status 0x%08x", Status); + ERR("Status 0x%08x\n", Status); return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); } Index: dll/win32/msafd/misc/sndrcv.c =================================================================== --- dll/win32/msafd/misc/sndrcv.c (revision 73320) +++ dll/win32/msafd/misc/sndrcv.c (working copy) @@ -140,21 +140,51 @@ 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); + } - Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); + 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); + } + + 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); +} + int WSPAPI WSPRecv(SOCKET Handle, @@ -169,9 +199,9 @@ { 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; @@ -200,38 +230,50 @@ 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, 1, 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; } } @@ -251,12 +293,12 @@ 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; } @@ -263,23 +305,25 @@ 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 */ @@ -289,25 +333,23 @@ 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"); @@ -314,11 +356,23 @@ return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead); } + 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); + /* Return the Flags */ - *ReceiveFlags = 0; + if (ReceiveFlags) + { + *ReceiveFlags = 0; - switch (Status) - { + switch (Status) + { case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; break; @@ -328,22 +382,27 @@ case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; + } } - /* Re-enable Async Event */ - if (*ReceiveFlags & MSG_OOB) + if (Status == STATUS_SUCCESS) { - SockReenableAsyncSelectEvent(Socket, FD_OOB); + /* Re-enable Async Event */ + if (ReceiveFlags && *ReceiveFlags & MSG_OOB) + { + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + SockReenableAsyncSelectEvent(Socket, FD_READ); + } } - 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 ); @@ -365,14 +424,16 @@ { 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) @@ -419,40 +480,52 @@ 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, 1, 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; } } @@ -472,12 +545,12 @@ 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; } @@ -484,23 +557,25 @@ 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 */ @@ -510,15 +585,15 @@ 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; } @@ -530,11 +605,23 @@ 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; @@ -544,22 +631,27 @@ case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; + } } - /* Re-enable Async Event */ - if (*ReceiveFlags & MSG_OOB) + if (Status == STATUS_SUCCESS) { - SockReenableAsyncSelectEvent(Socket, FD_OOB); + /* Re-enable Async Event */ + if (ReceiveFlags && *ReceiveFlags & MSG_OOB) + { + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + SockReenableAsyncSelectEvent(Socket, FD_READ); + } } - 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 ); @@ -580,14 +672,16 @@ { 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) @@ -603,19 +697,29 @@ 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, 1, FALSE ); if( !NT_SUCCESS(Status) ) - return -1; + { + HeapFree(GlobalHeap, 0, SendInfo); + return SOCKET_ERROR; + } - TRACE("Called\n"); - /* 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) @@ -622,11 +726,11 @@ { 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; } } @@ -645,12 +749,12 @@ 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; } @@ -657,23 +761,26 @@ 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 */ @@ -683,15 +790,15 @@ 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; } @@ -703,15 +810,24 @@ 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 ); @@ -733,10 +849,10 @@ { 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; @@ -744,6 +860,8 @@ HANDLE SockEvent; PSOCKET_INFORMATION Socket; + TRACE("WSPSendTo Called (%x)\n", Handle); + /* Get the Socket Structure associate to this Socket */ Socket = GetSocketStructure(Handle); if (!Socket) @@ -803,6 +921,17 @@ 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, 1, FALSE); @@ -809,6 +938,7 @@ if (!NT_SUCCESS(Status)) { + HeapFree(GlobalHeap, 0, SendInfo); HeapFree(GlobalHeap, 0, RemoteAddress); if (BindAddress != NULL) { @@ -823,11 +953,11 @@ 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) @@ -844,12 +974,12 @@ 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; } @@ -856,23 +986,28 @@ 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, @@ -880,21 +1015,21 @@ 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); @@ -905,13 +1040,25 @@ 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); Index: dll/win32/msafd/msafd.h =================================================================== --- dll/win32/msafd/msafd.h (revision 73320) +++ dll/win32/msafd/msafd.h (working copy) @@ -129,13 +129,38 @@ 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; + SOCKET WSPAPI WSPAccept( @@ -499,6 +524,9 @@ DWORD Received, LPDWORD ReturnedBytes) { + /* Allow for APC to be processed */ + SleepEx(0, TRUE); + if (Errno) { *Errno = TranslateNtStatusError(Status); @@ -510,7 +538,7 @@ } 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; Index: drivers/network/afd/afd/tdi.c =================================================================== --- drivers/network/afd/afd/tdi.c (revision 73320) +++ drivers/network/afd/afd/tdi.c (working copy) @@ -955,11 +955,9 @@ 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( @@ -1228,11 +1226,9 @@ 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( Index: drivers/network/afd/afd/write.c =================================================================== --- drivers/network/afd/afd/write.c (revision 73320) +++ drivers/network/afd/afd/write.c (working copy) @@ -379,6 +379,10 @@ 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 @@ { 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)); @@ -641,6 +645,10 @@ 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, @@ -652,7 +660,7 @@ { 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));