Index: dll/win32/msafd/misc/dllmain.c =================================================================== --- dll/win32/msafd/misc/dllmain.c (revision 74695) +++ dll/win32/msafd/misc/dllmain.c (working copy) @@ -1464,6 +1464,11 @@ if (lpErrno) *lpErrno = WSAENOTSOCK; return SOCKET_ERROR; } + if (!Socket->SharedData->Listening) + { + if (lpErrno) *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } if ((SocketAddress && !SocketAddressLength) || (SocketAddressLength && !SocketAddress) || (SocketAddressLength && *SocketAddressLength < sizeof(SOCKADDR))) @@ -1813,6 +1818,61 @@ 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); + + if (0 != (Context->lpSocket->SharedData->AsyncEvents & FD_CONNECT)) + { + /* Make the Notification */ + (Upcalls.lpWPUPostMessage)(Context->lpSocket->SharedData->hWnd, + Context->lpSocket->SharedData->wMsg, + Context->lpSocket->Handle, + WSAMAKESELECTREPLY(FD_CONNECT, 0)); + } + + 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, @@ -1824,7 +1884,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; @@ -1835,8 +1896,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); @@ -1846,15 +1909,6 @@ return SOCKET_ERROR; } - Status = NtCreateEvent(&SockEvent, - EVENT_ALL_ACCESS, - NULL, - 1, - FALSE); - - if (!NT_SUCCESS(Status)) - return SOCKET_ERROR; - /* Bind us First */ if (Socket->SharedData->State == SocketOpen) { @@ -1862,10 +1916,7 @@ BindAddressLength = Socket->HelperData->MaxWSAddressLength; BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength); if (!BindAddress) - { - NtClose(SockEvent); return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - } Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext, BindAddress, &BindAddressLength); @@ -1874,6 +1925,15 @@ return SOCKET_ERROR; } + Status = NtCreateEvent(&SockEvent, + EVENT_ALL_ACCESS, + NULL, + 1, + FALSE); + + if (!NT_SUCCESS(Status)) + return SOCKET_ERROR; + /* Set the Connect Data */ if (lpCallerData != NULL) { @@ -1882,7 +1942,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA, lpCallerData->buf, ConnectDataLength, @@ -1892,7 +1952,7 @@ if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1903,7 +1963,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) @@ -1920,16 +1980,7 @@ SocketAddress->sa_data, SocketDataLength); - /* - * Disable FD_WRITE and FD_CONNECT - * The latter fixes a race condition where the FD_CONNECT is re-enabled - * 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) - { - Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; - } + Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT; /* Tell AFD that we want Connection Data back, have it allocate a buffer */ if (lpCalleeData != NULL) @@ -1939,7 +1990,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_SET_CONNECT_DATA_SIZE, &InConnectDataLength, sizeof(InConnectDataLength), @@ -1950,7 +2001,7 @@ if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; + Status = IOSB->Status; } if (Status != STATUS_SUCCESS) @@ -1962,18 +2013,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, @@ -1982,16 +2043,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 */ @@ -2001,7 +2079,7 @@ SockEvent, NULL, NULL, - &IOSB, + IOSB, IOCTL_AFD_GET_CONNECT_DATA, NULL, 0, @@ -2011,23 +2089,27 @@ 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); - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - SockReenableAsyncSelectEvent(Socket, FD_CONNECT); - NtClose(SockEvent); + if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT)) + { + /* Make the Notification */ + (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, + Socket->SharedData->wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_CONNECT, 0)); + } + if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT)) { Errno = Socket->HelperData->WSHNotify(Socket->HelperContext, @@ -2958,6 +3040,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; @@ -3147,9 +3232,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); } @@ -3166,7 +3252,7 @@ IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3198,12 +3284,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; } @@ -3211,15 +3297,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; @@ -3240,22 +3325,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) @@ -3271,10 +3358,7 @@ *Boolean = InfoData.Information.Boolean; } - NtClose( SockEvent ); - - return NO_ERROR; - + return MsafdReturnWithErrno(Status, NULL, IOSB->Information, NULL); } @@ -3291,7 +3375,7 @@ IO_STATUS_BLOCK DummyIOSB; AFD_INFO InfoData; NTSTATUS Status; - PAFDAPCCONTEXT APCContext; + PAFDINFOAPCCONTEXT APCContext; PIO_APC_ROUTINE APCFunction; HANDLE Event = NULL; HANDLE SockEvent; @@ -3337,12 +3421,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; } @@ -3350,15 +3434,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; @@ -3379,9 +3462,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; } @@ -3392,10 +3475,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); } @@ -3697,22 +3780,6 @@ } break; - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - case AFD_EVENT_CONNECT: - case AFD_EVENT_CONNECT_FAIL: - if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) && - 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT)) - { - /* Make the Notification */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, - Socket->SharedData->wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CONNECT, 0)); - /* Disable this event forever; */ - Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT; - } - break; - case AFD_EVENT_ACCEPT: if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) && 0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT)) @@ -3795,12 +3862,6 @@ AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; } - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - if (lNetworkEvents & FD_CONNECT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; - } - if (lNetworkEvents & FD_CLOSE) { AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; Index: dll/win32/msafd/misc/event.c =================================================================== --- dll/win32/msafd/misc/event.c (revision 74695) +++ 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 74695) +++ 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) @@ -381,18 +442,6 @@ *lpErrno = WSAENOTSOCK; return SOCKET_ERROR; } - if (!lpNumberOfBytesRead && !lpOverlapped) - { - if (lpErrno) - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } - if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0) - { - if (lpErrno) - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS)) { @@ -408,6 +457,19 @@ lpErrno); } + if (!lpNumberOfBytesRead && !lpOverlapped) + { + if (lpErrno) + *lpErrno = WSAEFAULT; + return SOCKET_ERROR; + } + if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0) + { + if (lpErrno) + *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } + /* Bind us First */ if (Socket->SharedData->State == SocketOpen) { @@ -419,40 +481,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 +546,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 +558,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 +586,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 +606,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 +632,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 +673,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 +698,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 +727,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 +750,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 +762,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 +791,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 +811,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 +850,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 +861,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) @@ -752,12 +871,6 @@ *lpErrno = WSAENOTSOCK; return SOCKET_ERROR; } - if (!lpNumberOfBytesSent && !lpOverlapped) - { - if (lpErrno) - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS)) { @@ -773,6 +886,13 @@ lpErrno); } + if (!lpNumberOfBytesSent && !lpOverlapped) + { + if (lpErrno) + *lpErrno = WSAEFAULT; + return SOCKET_ERROR; + } + /* Bind us First */ if (Socket->SharedData->State == SocketOpen) { @@ -803,6 +923,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 +940,7 @@ if (!NT_SUCCESS(Status)) { + HeapFree(GlobalHeap, 0, SendInfo); HeapFree(GlobalHeap, 0, RemoteAddress); if (BindAddress != NULL) { @@ -823,11 +955,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 +976,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 +988,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 +1017,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 +1042,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 74695) +++ 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;