@@ -868,6 +868,7 @@ WSPBind(SOCKET Handle,
868868 NTSTATUS Status ;
869869 SOCKADDR_INFO SocketInfo ;
870870 HANDLE SockEvent ;
871+ ULONG connectSize ;
871872
872873 /* Get the Socket Structure associate to this Socket*/
873874 Socket = GetSocketStructure (Handle );
@@ -909,8 +910,10 @@ WSPBind(SOCKET Handle,
909910 return SOCKET_ERROR ;
910911 }
911912
913+ connectSize = FIELD_OFFSET (AFD_BIND_DATA , Address .Address [SocketAddressLength ]);
914+
912915 /* See below */
913- BindData = HeapAlloc (GlobalHeap , 0 , 0xA + SocketAddressLength );
916+ BindData = HeapAlloc (GlobalHeap , 0 , connectSize );
914917 if (!BindData )
915918 {
916919 return MsafdReturnWithErrno (STATUS_INSUFFICIENT_RESOURCES , lpErrno , 0 , NULL );
@@ -950,9 +953,9 @@ WSPBind(SOCKET Handle,
950953 & IOSB ,
951954 IOCTL_AFD_BIND ,
952955 BindData ,
953- 0xA + Socket -> SharedData -> SizeOfLocalAddress , /* Can't figure out a way to calculate this in C*/
956+ connectSize ,
954957 BindData ,
955- 0xA + Socket -> SharedData -> SizeOfLocalAddress ); /* Can't figure out a way to calculate this C */
958+ connectSize );
956959
957960 /* Wait for return */
958961 if (Status == STATUS_PENDING )
@@ -2173,6 +2176,106 @@ WSPConnect(SOCKET Handle,
21732176
21742177 return MsafdReturnWithErrno (Status , lpErrno , 0 , NULL );
21752178}
2179+
2180+ BOOL
2181+ WSPAPI
2182+ WSPConnectEx (
2183+ _In_ SOCKET Handle ,
2184+ _In_ const struct sockaddr * SocketAddress ,
2185+ _In_ int SocketAddressLength ,
2186+ _In_ PVOID lpSendBuffer ,
2187+ _In_ DWORD dwSendDataLength ,
2188+ _Out_ LPDWORD lpdwBytesSent ,
2189+ _Inout_ LPOVERLAPPED lpOverlapped )
2190+ {
2191+ IO_STATUS_BLOCK DummyIOSB ;
2192+ PIO_STATUS_BLOCK IOSB = & DummyIOSB ;
2193+ PAFD_SUPER_CONNECT_INFO ConnectInfo = NULL ;
2194+ PSOCKET_INFORMATION Socket ;
2195+ NTSTATUS Status ;
2196+ int SocketDataLength ;
2197+ UCHAR Buffer [128 ];
2198+
2199+ if (!lpOverlapped )
2200+ {
2201+ SetLastError (ERROR_INVALID_PARAMETER );
2202+ return FALSE;
2203+ }
2204+
2205+ if (!lpSendBuffer && dwSendDataLength )
2206+ {
2207+ SetLastError (ERROR_INVALID_PARAMETER );
2208+ return FALSE;
2209+ }
2210+
2211+ /* Get the Socket Structure associate to this Socket*/
2212+ Socket = GetSocketStructure (Handle );
2213+ if (!Socket )
2214+ {
2215+ SetLastError (WSAENOTSOCK );
2216+ return FALSE;
2217+ }
2218+
2219+
2220+ /* Cannot call on connectionless socket */
2221+ if (SocketAddressLength > ARRAYSIZE (Buffer ) - sizeof (AFD_CONNECT_INFO ) || Socket -> SharedData -> ServiceFlags1 & XP1_CONNECTIONLESS )
2222+ {
2223+ SetLastError (WSAEFAULT );
2224+ return SOCKET_ERROR ;
2225+ }
2226+
2227+ if (Socket -> SharedData -> State == SocketOpen )
2228+ {
2229+ /* Socket already must be bound */
2230+ SetLastError (WSAEINVAL );
2231+ return FALSE;
2232+ }
2233+
2234+ ConnectInfo = (PAFD_SUPER_CONNECT_INFO )Buffer ;
2235+ ConnectInfo -> SanActive = FALSE;
2236+
2237+ /* Calculate the size of SocketAddress->sa_data */
2238+ SocketDataLength = SocketAddressLength - FIELD_OFFSET (struct sockaddr , sa_data );
2239+
2240+ /* Set up Address in TDI Format */
2241+ ConnectInfo -> RemoteAddress .TAAddressCount = 1 ;
2242+ ConnectInfo -> RemoteAddress .Address [0 ].AddressLength = SocketDataLength ;
2243+ ConnectInfo -> RemoteAddress .Address [0 ].AddressType = SocketAddress -> sa_family ;
2244+ RtlCopyMemory (ConnectInfo -> RemoteAddress .Address [0 ].Address ,
2245+ SocketAddress -> sa_data ,
2246+ SocketDataLength );
2247+
2248+ /*
2249+ * Disable FD_WRITE and FD_CONNECT.
2250+ * The latter fixes a race condition where the FD_CONNECT is re-enabled
2251+ * at the end of this function right after the Async Thread disables it.
2252+ * This should only happen at the *next* WSPConnect.
2253+ */
2254+ if (Socket -> SharedData -> AsyncEvents & FD_CONNECT )
2255+ {
2256+ Socket -> SharedData -> AsyncDisabledEvents |= (FD_CONNECT | FD_WRITE );
2257+ }
2258+
2259+ IOSB = (PIO_STATUS_BLOCK )lpOverlapped ;
2260+ IOSB -> Status = STATUS_PENDING ;
2261+
2262+ /* Send IOCTL */
2263+ Status = NtDeviceIoControlFile ((HANDLE )Handle ,
2264+ lpOverlapped -> hEvent ,
2265+ NULL ,
2266+ lpOverlapped -> hEvent ? NULL : lpOverlapped ,
2267+ IOSB ,
2268+ IOCTL_AFD_SUPER_CONNECT ,
2269+ ConnectInfo ,
2270+ FIELD_OFFSET (AFD_SUPER_CONNECT_INFO , RemoteAddress .Address [0 ].Address [SocketDataLength ]),
2271+ lpSendBuffer ,
2272+ dwSendDataLength );
2273+
2274+ SetLastError (TranslateNtStatusError (Status ));
2275+
2276+ return Status == STATUS_SUCCESS ;
2277+ }
2278+
21762279int
21772280WSPAPI
21782281WSPShutdown (SOCKET Handle ,
@@ -2882,6 +2985,116 @@ WSPGetSockOpt(IN SOCKET Handle,
28822985 return (Errno == NO_ERROR ) ? NO_ERROR : SOCKET_ERROR ;
28832986}
28842987
2988+ static
2989+ INT
2990+ NTAPI
2991+ MsafdUpdateConnectionContext (
2992+ _In_ SOCKET Handle ,
2993+ _Out_ LPINT lpErrno )
2994+ {
2995+ IO_STATUS_BLOCK DummyIOSB ;
2996+ PIO_STATUS_BLOCK IOSB = & DummyIOSB ;
2997+ NTSTATUS Status ;
2998+ SOCK_SHARED_INFO SharedData ;
2999+ AFD_TDI_HANDLE_DATA HandleData ;
3000+ HANDLE SockEvent ;
3001+ PSOCKET_INFORMATION Socket = GetSocketStructure (Handle );
3002+
3003+ if (!Socket )
3004+ {
3005+ if (lpErrno ) * lpErrno = WSAENOTSOCK ;
3006+ return SOCKET_ERROR ;
3007+ }
3008+
3009+ if (Socket -> SharedData -> State == SocketConnected )
3010+ {
3011+ return NO_ERROR ;
3012+ }
3013+
3014+ /* Get the socket context from AFD because when ConnectEx is used, this information is not updated. */
3015+ Status = NtCreateEvent (& SockEvent ,
3016+ EVENT_ALL_ACCESS ,
3017+ NULL ,
3018+ SynchronizationEvent ,
3019+ FALSE);
3020+ if (!NT_SUCCESS (Status ))
3021+ goto Quit ;
3022+
3023+ Status = NtDeviceIoControlFile ((HANDLE )Handle ,
3024+ SockEvent ,
3025+ NULL ,
3026+ NULL ,
3027+ IOSB ,
3028+ IOCTL_AFD_GET_CONTEXT ,
3029+ NULL ,
3030+ 0 ,
3031+ & SharedData ,
3032+ sizeof (SharedData ));
3033+
3034+ if (Status == STATUS_PENDING )
3035+ {
3036+ MsafdWaitForAlert (SockEvent );
3037+ Status = IOSB -> Status ;
3038+ }
3039+
3040+ if (!NT_SUCCESS (Status ))
3041+ goto Quit ;
3042+
3043+ ULONG flags = AFD_CONNECTION_HANDLE | AFD_ADDRESS_HANDLE ;
3044+
3045+ /* Get TDI handles from AFD */
3046+ Status = NtDeviceIoControlFile ((HANDLE )Handle ,
3047+ SockEvent ,
3048+ NULL ,
3049+ NULL ,
3050+ IOSB ,
3051+ IOCTL_AFD_GET_TDI_HANDLES ,
3052+ & flags ,
3053+ sizeof (flags ),
3054+ & HandleData ,
3055+ sizeof (HandleData ));
3056+
3057+ if (Status == STATUS_PENDING )
3058+ {
3059+ MsafdWaitForAlert (SockEvent );
3060+ Status = IOSB -> Status ;
3061+ }
3062+
3063+ /* Bail out if the socket was destroyed */
3064+ if (!NT_SUCCESS (Status ))
3065+ goto Quit ;
3066+
3067+ Socket -> SharedData -> State = SharedData .State ;
3068+
3069+ if (SharedData .State == SocketConnected )
3070+ {
3071+ /* Socket is now connected, update usermode msafd socket structure, same as the end of WSPConnect */
3072+ Socket -> TdiConnectionHandle = HandleData .TdiConnectionHandle ;
3073+ Socket -> TdiAddressHandle = HandleData .TdiAddressHandle ;
3074+ Socket -> SharedData -> ConnectTime = SharedData .ConnectTime ;
3075+
3076+ /* Re-enable Async Event */
3077+ SockReenableAsyncSelectEvent (Socket , FD_WRITE );
3078+
3079+ /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3080+ SockReenableAsyncSelectEvent (Socket , FD_CONNECT );
3081+
3082+ Socket -> HelperData -> WSHNotify (Socket -> HelperContext ,
3083+ Socket -> Handle ,
3084+ Socket -> TdiAddressHandle ,
3085+ Socket -> TdiConnectionHandle ,
3086+ WSH_NOTIFY_CONNECT );
3087+ }
3088+
3089+ NtClose (SockEvent );
3090+
3091+ Quit :
3092+ if (Status == STATUS_SUCCESS )
3093+ return NO_ERROR ;
3094+ if (lpErrno ) * lpErrno = TranslateNtStatusError (Status );
3095+ return SOCKET_ERROR ;
3096+ }
3097+
28853098INT
28863099WSPAPI
28873100WSPSetSockOpt (
@@ -2902,7 +3115,7 @@ WSPSetSockOpt(
29023115 if (lpErrno ) * lpErrno = WSAENOTSOCK ;
29033116 return SOCKET_ERROR ;
29043117 }
2905- if (!optval )
3118+ if (!optval && optlen )
29063119 {
29073120 if (lpErrno ) * lpErrno = WSAEFAULT ;
29083121 return SOCKET_ERROR ;
@@ -3022,6 +3235,9 @@ WSPSetSockOpt(
30223235
30233236 return NO_ERROR ;
30243237
3238+ case SO_UPDATE_CONNECT_CONTEXT :
3239+ return MsafdUpdateConnectionContext (s , lpErrno );
3240+
30253241 case SO_ERROR :
30263242 if (optlen < sizeof (INT ))
30273243 {
0 commit comments