- Fix linger and graceful disconnect
- Fix a crash in WSPGetSockName and WSPGetPeerName exposed by ws2_32 winetest sock

svn path=/trunk/; revision=52193
This commit is contained in:
Cameron Gutman 2011-06-11 17:49:30 +00:00
parent e39c778ae1
commit 56c66ff1fd

View file

@ -401,6 +401,7 @@ WSPCloseSocket(IN SOCKET Handle,
HANDLE SockEvent; HANDLE SockEvent;
AFD_DISCONNECT_INFO DisconnectInfo; AFD_DISCONNECT_INFO DisconnectInfo;
SOCKET_STATE OldState; SOCKET_STATE OldState;
LONG LingerWait = -1;
/* Create the Wait Event */ /* Create the Wait Event */
Status = NtCreateEvent(&SockEvent, Status = NtCreateEvent(&SockEvent,
@ -453,7 +454,6 @@ WSPCloseSocket(IN SOCKET Handle,
/* FIXME: Should we do this on Datagram Sockets too? */ /* FIXME: Should we do this on Datagram Sockets too? */
if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff)) if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
{ {
ULONG LingerWait;
ULONG SendsInProgress; ULONG SendsInProgress;
ULONG SleepWait; ULONG SleepWait;
@ -477,7 +477,11 @@ WSPCloseSocket(IN SOCKET Handle,
/* Bail out if no more sends are pending */ /* Bail out if no more sends are pending */
if (!SendsInProgress) if (!SendsInProgress)
{
LingerWait = -1;
break; break;
}
/* /*
* We have to execute a sleep, so it's kind of like * We have to execute a sleep, so it's kind of like
* a block. If the socket is Nonblock, we cannot * a block. If the socket is Nonblock, we cannot
@ -502,15 +506,14 @@ WSPCloseSocket(IN SOCKET Handle,
Sleep(SleepWait); Sleep(SleepWait);
LingerWait -= SleepWait; LingerWait -= SleepWait;
} }
}
/* if (OldState == SocketConnected)
* We have reached the timeout or sends are over. {
* Disconnect if the timeout has been reached.
*/
if (LingerWait <= 0) if (LingerWait <= 0)
{ {
DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
/* Send IOCTL */ /* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle, Status = NtDeviceIoControlFile((HANDLE)Handle,
@ -1564,6 +1567,7 @@ WSPConnect(SOCKET Handle,
if (Status != STATUS_SUCCESS) if (Status != STATUS_SUCCESS)
goto notify; goto notify;
Socket->SharedData.State = SocketConnected;
Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
/* Get any pending connect data */ /* Get any pending connect data */
@ -1742,6 +1746,13 @@ WSPGetSockName(IN SOCKET Handle,
return SOCKET_ERROR; return SOCKET_ERROR;
} }
if (!Name || !NameLength)
{
NtClose(SockEvent);
*lpErrno = WSAEFAULT;
return SOCKET_ERROR;
}
/* Allocate a buffer for the address */ /* Allocate a buffer for the address */
TdiAddressSize = TdiAddressSize =
sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress; sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress;
@ -1836,6 +1847,20 @@ WSPGetPeerName(IN SOCKET s,
return SOCKET_ERROR; return SOCKET_ERROR;
} }
if (Socket->SharedData.State != SocketConnected)
{
NtClose(SockEvent);
*lpErrno = WSAENOTCONN;
return SOCKET_ERROR;
}
if (!Name || !NameLength)
{
NtClose(SockEvent);
*lpErrno = WSAEFAULT;
return SOCKET_ERROR;
}
/* Allocate a buffer for the address */ /* Allocate a buffer for the address */
TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength; TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength;
SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);