739 cs130_tom 1.1 {
740 if (ptb->se_len >= size ) return ptb->se_buffer;
741 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
742 }
743 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
744 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
745 return ptb->se_buffer;
746 }
747
748 static struct WS_protoent *check_buffer_pe(int size)
749 {
750 struct per_thread_data * ptb = get_per_thread_data();
751 if (ptb->pe_buffer)
752 {
753 if (ptb->pe_len >= size ) return ptb->pe_buffer;
754 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
755 }
756 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
757 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
758 return ptb->pe_buffer;
759 }
760 cs130_tom 1.1
761 /* ----------------------------------- i/o APIs */
762
763 #ifdef HAVE_IPX
764 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
765 #else
766 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
767 #endif
768
769
770 /**********************************************************************/
771
772 /* Returns the converted address if successful, NULL if it was too small to
773 * start with. Note that the returned pointer may be the original pointer
774 * if no conversion is necessary.
775 */
776 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
777 {
778 switch (wsaddr->sa_family)
779 {
780 #ifdef HAVE_IPX
781 cs130_tom 1.1 case WS_AF_IPX:
782 {
783 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
784 struct sockaddr_ipx* uipx;
785
786 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
787 return NULL;
788
789 *uaddrlen=sizeof(struct sockaddr_ipx);
790 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
791 uipx->sipx_family=AF_IPX;
792 uipx->sipx_port=wsipx->sa_socket;
793 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
794 * in one go
795 */
796 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
797 #ifdef IPX_FRAME_NONE
798 uipx->sipx_type=IPX_FRAME_NONE;
799 #endif
800 return (const struct sockaddr*)uipx;
801 }
802 cs130_tom 1.1 #endif
803
804 default:
805 if (wsaddrlen<sizeof(struct WS_sockaddr))
806 return NULL;
807
808 /* No conversion needed, just return the original address */
809 *uaddrlen=wsaddrlen;
810 return (const struct sockaddr*)wsaddr;
811 }
812 }
813
814 /* Allocates a Unix sockaddr structure to receive the data */
815 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
816 {
817 if (wsaddr==NULL)
818 {
819 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
820
821 /* This is not strictly the right thing to do. Hope it works however */
822 *uaddrlen=0;
823 cs130_tom 1.1
824 return NULL;
825 }
826
827 if (*wsaddrlen==0)
828 *uaddrlen=0;
829 else
830 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
831
832 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
833 }
834
835 /* Returns 0 if successful, -1 if the buffer is too small */
836 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
837 {
838 int res;
839
840 switch(uaddr->sa_family)
841 {
842 #ifdef HAVE_IPX
843 case AF_IPX:
844 cs130_tom 1.1 {
845 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
846 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
847
848 res=-1;
849 switch (*wsaddrlen) /* how much can we copy? */
850 {
851 default:
852 res=0; /* enough */
853 *wsaddrlen=uaddrlen;
854 wsipx->sa_socket=uipx->sipx_port;
855 /* fall through */
856 case 13:
857 case 12:
858 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
859 /* fall through */
860 case 11:
861 case 10:
862 case 9:
863 case 8:
864 case 7:
865 cs130_tom 1.1 case 6:
866 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
867 /* fall through */
868 case 5:
869 case 4:
870 case 3:
871 case 2:
872 wsipx->sa_family=WS_AF_IPX;
873 /* fall through */
874 case 1:
875 case 0:
876 /* way too small */
877 break;
878 }
879 }
880 break;
881 #endif
882
883 default:
884 /* No conversion needed */
885 memcpy(wsaddr,uaddr,*wsaddrlen);
886 cs130_tom 1.1 if (*wsaddrlen<uaddrlen) {
887 res=-1;
888 } else {
889 *wsaddrlen=uaddrlen;
890 res=0;
891 }
892 }
893 return res;
894 }
895
896 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
897 * ws_sockaddr_alloc
898 */
899 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
900 {
901 if (uaddr!=(const struct sockaddr*)wsaddr)
902 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
903 }
904
905 /**************************************************************************
906 * Functions for handling overlapped I/O
907 cs130_tom 1.1 **************************************************************************/
908
909 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
910 {
911 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
912
913 wine_server_release_fd( as->hSocket, as->fd );
914 if ( as->event != INVALID_HANDLE_VALUE )
915 NtSetEvent( as->event, NULL );
916
917 if (as->completion_func)
918 as->completion_func( NtStatusToWSAError (iosb->u.Status),
919 iosb->Information, as->user_overlapped, as->flags );
920 if ( !as->user_overlapped )
921 {
922 #if 0
923 /* FIXME: I don't think this is really used */
924 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
925 WSACloseEvent( as->overlapped->hEvent );
926 #endif
927 HeapFree( GetProcessHeap(), 0, iosb );
928 cs130_tom 1.1 }
929
930 HeapFree( GetProcessHeap(), 0, as->iovec );
931 HeapFree( GetProcessHeap(), 0, as );
932 }
933
934 /***********************************************************************
935 * WS2_make_async (INTERNAL)
936 */
937
938 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
939 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
940 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
941
942 inline static struct ws2_async*
943 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
944 LPDWORD lpFlags, struct WS_sockaddr *addr,
945 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
946 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
947 IO_STATUS_BLOCK **piosb)
948 {
949 cs130_tom 1.1 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
950
951 TRACE( "wsa %p\n", wsa );
952
953 if (!wsa)
954 return NULL;
955
956 wsa->hSocket = (HANDLE) s;
957 wsa->mode = mode;
958 switch (mode)
959 {
960 case ws2m_read:
961 case ws2m_sd_read:
962 wsa->flags = *lpFlags;
963 wsa->addrlen.ptr = addrlen;
964 break;
965 case ws2m_write:
966 case ws2m_sd_write:
967 wsa->flags = 0;
968 wsa->addrlen.val = *addrlen;
969 break;
970 cs130_tom 1.1 default:
971 ERR("Invalid async mode: %d\n", mode);
972 }
973 wsa->user_overlapped = lpOverlapped;
974 wsa->completion_func = lpCompletionRoutine;
975 wsa->iovec = iovec;
976 wsa->n_iovecs = dwBufferCount;
977 wsa->addr = addr;
978 wsa->fd = fd;
979 wsa->event = INVALID_HANDLE_VALUE;
980
981 if ( lpOverlapped )
982 {
983 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
984 if (!lpCompletionRoutine)
985 {
986 wsa->event = lpOverlapped->hEvent;
987 NtResetEvent(wsa->event, NULL);
988 }
989 }
990 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
991 cs130_tom 1.1 goto error;
992
993 (*piosb)->Information = 0;
994 (*piosb)->u.Status = STATUS_PENDING;
995 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
996 wsa, wsa->hSocket, wsa->event, wsa->fd,
997 *piosb, wsa->user_overlapped, wsa->completion_func );
998
999 return wsa;
1000
1001 error:
1002 TRACE("Error\n");
1003 HeapFree( GetProcessHeap(), 0, wsa );
1004 return NULL;
1005 }
1006
1007 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1008 {
1009 PIO_APC_ROUTINE apc;
1010 int type;
1011 NTSTATUS status;
1012 cs130_tom 1.1
1013 switch (wsa->mode)
1014 {
1015 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1016 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1017 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1018 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1019 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1020 }
1021
1022 SERVER_START_REQ( register_async )
1023 {
1024 req->handle = wsa->hSocket;
1025 req->io_apc = apc;
1026 req->io_sb = iosb;
1027 req->io_user = wsa;
1028 req->type = type;
1029 req->count = iosb->Information;
1030 status = wine_server_call( req );
1031 }
1032 SERVER_END_REQ;
1033 cs130_tom 1.1
1034 if ( status ) iosb->u.Status = status;
1035 if ( iosb->u.Status != STATUS_PENDING )
1036 {
1037 (apc)( wsa, iosb, iosb->u.Status );
1038 return iosb->u.Status;
1039 }
1040 NtCurrentTeb()->num_async_io++;
1041 return STATUS_SUCCESS;
1042 }
1043
1044 /***********************************************************************
1045 * WS2_recv (INTERNAL)
1046 *
1047 * Workhorse for both synchronous and asynchronous recv() operations.
1048 */
1049 static int WS2_recv( int fd, struct iovec* iov, int count,
1050 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1051 LPDWORD lpFlags )
1052 {
1053 struct msghdr hdr;
1054 cs130_tom 1.1 int n;
1055 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1056 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1057
1058 hdr.msg_name = NULL;
1059
1060 if ( lpFrom )
1061 {
1062 hdr.msg_namelen = *lpFromlen;
1063 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1064 if ( !hdr.msg_name )
1065 {
1066 WSASetLastError( WSAEFAULT );
1067 n = -1;
1068 goto out;
1069 }
1070 }
1071 else
1072 hdr.msg_namelen = 0;
1073
1074 hdr.msg_iov = iov;
1075 cs130_tom 1.1 hdr.msg_iovlen = count;
1076 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1077 hdr.msg_accrights = NULL;
1078 hdr.msg_accrightslen = 0;
1079 #else
1080 hdr.msg_control = NULL;
1081 hdr.msg_controllen = 0;
1082 hdr.msg_flags = 0;
1083 #endif
1084
1085 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1086 {
1087 TRACE( "recvmsg error %d\n", errno);
1088 goto out;
1089 }
1090
1091 if ( lpFrom &&
1092 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1093 lpFrom, lpFromlen ) != 0 )
1094 {
1095 /* The from buffer was too small, but we read the data
1096 cs130_tom 1.1 * anyway. Is that really bad?
1097 */
1098 WSASetLastError( WSAEFAULT );
1099 WARN( "Address buffer too small\n" );
1100 }
1101
1102 out:
1103
1104 ws_sockaddr_free( hdr.msg_name, lpFrom );
1105 TRACE("-> %d\n", n);
1106 return n;
1107 }
1108
1109 /***********************************************************************
1110 * WS2_async_recv (INTERNAL)
1111 *
1112 * Handler for overlapped recv() operations.
1113 */
1114 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1115 {
1116 ws2_async* wsa = (ws2_async*) ovp;
1117 cs130_tom 1.1 int result, err;
1118
1119 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1120
1121 switch (status)
1122 {
1123 case STATUS_ALERTED:
1124 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1125 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1126 if (result >= 0)
1127 {
1128 iosb->u.Status = STATUS_SUCCESS;
1129 iosb->Information = result;
1130 TRACE( "received %d bytes\n", result );
1131 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1132 }
1133 else
1134 {
1135 err = wsaErrno();
1136 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1137 {
1138 cs130_tom 1.1 iosb->u.Status = STATUS_PENDING;
1139 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1140 TRACE( "still pending\n" );
1141 }
1142 else
1143 {
1144 iosb->u.Status = err; /* FIXME: is this correct ???? */
1145 TRACE( "Error: %x\n", err );
1146 }
1147 }
1148 if (iosb->u.Status == STATUS_PENDING)
1149 ws2_queue_async(wsa, iosb);
1150 else
1151 ws2_async_terminate(wsa, iosb);
1152 break;
1153 default:
1154 FIXME( "status: %ld\n", status );
1155 iosb->u.Status = status;
1156 ws2_async_terminate(wsa, iosb);
1157 return;
1158 }
1159 cs130_tom 1.1 }
1160
1161 /***********************************************************************
1162 * WS2_send (INTERNAL)
1163 *
1164 * Workhorse for both synchronous and asynchronous send() operations.
1165 */
1166 static int WS2_send( int fd, struct iovec* iov, int count,
1167 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1168 {
1169 struct msghdr hdr;
1170 int n = -1;
1171 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1172 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1173
1174 hdr.msg_name = NULL;
1175
1176 if ( to )
1177 {
1178 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1179 if ( !hdr.msg_name )
1180 cs130_tom 1.1 {
1181 WSASetLastError( WSAEFAULT );
1182 goto out;
1183 }
1184
1185 #ifdef HAVE_IPX
1186 if(to->sa_family == WS_AF_IPX)
1187 {
1188 #ifdef SOL_IPX
1189 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1190 int val=0;
1191 int len=sizeof(int);
1192
1193 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1194 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1195 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1196 * ipx type in the sockaddr_opx structure with the stored value.
1197 */
1198 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1199 {
1200 TRACE("ptype: %d (fd:%d)\n", val, fd);
1201 cs130_tom 1.1 uipx->sipx_type = val;
1202 }
1203 #endif
1204 }
1205 #endif
1206
1207 }
1208 else
1209 hdr.msg_namelen = 0;
1210
1211 hdr.msg_iov = iov;
1212 hdr.msg_iovlen = count;
1213 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1214 hdr.msg_accrights = NULL;
1215 hdr.msg_accrightslen = 0;
1216 #else
1217 hdr.msg_control = NULL;
1218 hdr.msg_controllen = 0;
1219 hdr.msg_flags = 0;
1220 #endif
1221
1222 cs130_tom 1.1 n = sendmsg(fd, &hdr, dwFlags);
1223
1224 out:
1225 ws_sockaddr_free( hdr.msg_name, to );
1226 return n;
1227 }
1228
1229 /***********************************************************************
1230 * WS2_async_send (INTERNAL)
1231 *
1232 * Handler for overlapped send() operations.
1233 */
1234 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1235 {
1236 ws2_async* wsa = (ws2_async*) as;
1237 int result;
1238
1239 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1240
1241 switch (status)
1242 {
1243 cs130_tom 1.1 case STATUS_ALERTED:
1244 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1245 /* check to see if the data is ready (non-blocking) */
1246 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1247 wsa->addr, wsa->addrlen.val, wsa->flags );
1248
1249 if (result >= 0)
1250 {
1251 iosb->u.Status = STATUS_SUCCESS;
1252 iosb->Information = result;
1253 TRACE( "sent %d bytes\n", result );
1254 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1255 }
1256 else
1257 {
1258 int err = wsaErrno();
1259 if ( err == WSAEINTR )
1260 {
1261 iosb->u.Status = STATUS_PENDING;
1262 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1263 TRACE( "still pending\n" );
1264 cs130_tom 1.1 }
1265 else
1266 {
1267 /* We set the status to a winsock error code and check for that
1268 later in NtStatusToWSAError () */
1269 iosb->u.Status = err;
1270 TRACE( "Error: %x\n", err );
1271 }
1272 }
1273 if (iosb->u.Status == STATUS_PENDING)
1274 ws2_queue_async(wsa, iosb);
1275 else
1276 ws2_async_terminate(wsa, iosb);
1277 break;
1278 default:
1279 FIXME( "status: %ld\n", status );
1280 iosb->u.Status = status;
1281 ws2_async_terminate(wsa, iosb);
1282 return;
1283 }
1284
1285 cs130_tom 1.1 }
1286
1287 /***********************************************************************
1288 * WS2_async_shutdown (INTERNAL)
1289 *
1290 * Handler for shutdown() operations on overlapped sockets.
1291 */
1292 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1293 {
1294 ws2_async* wsa = (ws2_async*) as;
1295 int err = 1;
1296
1297 TRACE( "async %p %d\n", wsa, wsa->mode );
1298 switch (status)
1299 {
1300 case STATUS_ALERTED:
1301 switch ( wsa->mode )
1302 {
1303 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1304 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1305 default: ERR("invalid mode: %d\n", wsa->mode );
1306 cs130_tom 1.1 }
1307 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1308 if (iosb->u.Status == STATUS_PENDING)
1309 ws2_queue_async(wsa, iosb);
1310 else
1311 ws2_async_terminate(wsa, iosb);
1312 break;
1313 default:
1314 iosb->u.Status = status;
1315 ws2_async_terminate(wsa, iosb);
1316 break;
1317 }
1318
1319 }
1320
1321 /***********************************************************************
1322 * WS2_register_async_shutdown (INTERNAL)
1323 *
1324 * Helper function for WS_shutdown() on overlapped sockets.
1325 */
1326 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1327 cs130_tom 1.1 {
1328 struct ws2_async *wsa;
1329 int ret, err = WSAEFAULT;
1330 DWORD dwflags = 0;
1331 int len = 0;
1332 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1333 IO_STATUS_BLOCK *iosb;
1334
1335 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1336 if (!ovl)
1337 goto out;
1338
1339 ovl->hEvent = WSACreateEvent();
1340 if ( ovl->hEvent == WSA_INVALID_EVENT )
1341 goto out_free;
1342
1343 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1344 &dwflags, NULL, &len, ovl, NULL, &iosb );
1345 if ( !wsa )
1346 goto out_close;
1347
1348 cs130_tom 1.1 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1349 wsa->user_overlapped = NULL;
1350 if ( (ret = ws2_queue_async( wsa, iosb )) )
1351 {
1352 err = NtStatusToWSAError( ret );
1353 goto out;
1354 }
1355 /* Try immediate completion */
1356 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1357 return 0;
1358
1359 out_close:
1360 WSACloseEvent( ovl->hEvent );
1361 out_free:
1362 HeapFree( GetProcessHeap(), 0, iosb );
1363 HeapFree( GetProcessHeap(), 0, ovl );
1364 out:
1365 return err;
1366 }
1367
1368 /***********************************************************************
1369 cs130_tom 1.1 * accept (WS2_32.1)
1370 */
1371 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1372 int *addrlen32)
1373 {
1374 SOCKET as;
1375
1376 TRACE("socket %04x\n", s );
1377 if (_is_blocking(s))
1378 {
1379 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1380 if (fd == -1) return INVALID_SOCKET;
1381 /* block here */
1382 do_block(fd, POLLIN, -1);
1383 _sync_sock_state(s); /* let wineserver notice connection */
1384 release_sock_fd( s, fd );
1385 /* retrieve any error codes from it */
1386 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1387 /* FIXME: care about the error? */
1388 }
1389 SERVER_START_REQ( accept_socket )
1390 cs130_tom 1.1 {
1391 req->lhandle = SOCKET2HANDLE(s);
1392 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1393 req->inherit = TRUE;
1394 set_error( wine_server_call( req ) );
1395 as = HANDLE2SOCKET( reply->handle );
1396 }
1397 SERVER_END_REQ;
1398 if (as)
1399 {
1400 if (addr) WS_getpeername(as, addr, addrlen32);
1401 return as;
1402 }
1403 return INVALID_SOCKET;
1404 }
1405
1406 /***********************************************************************
1407 * bind (WS2_32.2)
1408 */
1409 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1410 {
1411 cs130_tom 1.1 int fd = get_sock_fd( s, 0, NULL );
1412 int res = SOCKET_ERROR;
1413
1414 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1415
1416 if (fd != -1)
1417 {
1418 if (!name || !SUPPORTED_PF(name->sa_family))
1419 {
1420 SetLastError(WSAEAFNOSUPPORT);
1421 }
1422 else
1423 {
1424 const struct sockaddr* uaddr;
1425 int uaddrlen;
1426
1427 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1428 if (uaddr == NULL)
1429 {
1430 SetLastError(WSAEFAULT);
1431 }
1432 cs130_tom 1.1 else
1433 {
1434 if (bind(fd, uaddr, uaddrlen) < 0)
1435 {
1436 int loc_errno = errno;
1437 WARN("\tfailure - errno = %i\n", errno);
1438 errno = loc_errno;
1439 switch (errno)
1440 {
1441 case EBADF:
1442 SetLastError(WSAENOTSOCK);
1443 break;
1444 case EADDRNOTAVAIL:
1445 SetLastError(WSAEINVAL);
1446 break;
1447 default:
1448 SetLastError(wsaErrno());
1449 break;
1450 }
1451 }
1452 else
1453 cs130_tom 1.1 {
1454 res=0; /* success */
1455 }
1456 ws_sockaddr_free(uaddr,name);
1457 }
1458 }
1459 release_sock_fd( s, fd );
1460 }
1461 return res;
1462 }
1463
1464 /***********************************************************************
1465 * closesocket (WS2_32.3)
1466 */
1467 int WINAPI WS_closesocket(SOCKET s)
1468 {
1469 TRACE("socket %04x\n", s);
1470 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1471 return SOCKET_ERROR;
1472 }
1473
1474 cs130_tom 1.1 /***********************************************************************
1475 * connect (WS2_32.4)
1476 */
1477 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1478 {
1479 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1480
1481 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1482
1483 if (fd != -1)
1484 {
1485 const struct sockaddr* uaddr;
1486 int uaddrlen;
1487
1488 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1489 if (uaddr == NULL)
1490 {
1491 SetLastError(WSAEFAULT);
1492 }
1493 else
1494 {
1495 cs130_tom 1.1 int rc;
1496
1497 rc=connect(fd, uaddr, uaddrlen);
1498 ws_sockaddr_free(uaddr,name);
1499 if (rc == 0)
1500 goto connect_success;
1501 }
1502
1503 if (errno == EINPROGRESS)
1504 {
1505 /* tell wineserver that a connection is in progress */
1506 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1507 FD_CONNECT|FD_READ|FD_WRITE,
1508 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1509 if (_is_blocking(s))
1510 {
1511 int result;
1512 /* block here */
1513 do_block(fd, POLLIN | POLLOUT, -1);
1514 _sync_sock_state(s); /* let wineserver notice connection */
1515 /* retrieve any error codes from it */
1516 cs130_tom 1.1 result = _get_sock_error(s, FD_CONNECT_BIT);
1517 if (result)
1518 SetLastError(result);
1519 else
1520 {
1521 goto connect_success;
1522 }
1523 }
1524 else
1525 {
1526 SetLastError(WSAEWOULDBLOCK);
1527 }
1528 }
1529 else
1530 {
1531 SetLastError(wsaErrno());
1532 }
1533 release_sock_fd( s, fd );
1534 }
1535 return SOCKET_ERROR;
1536
1537 cs130_tom 1.1 connect_success:
1538 release_sock_fd( s, fd );
1539 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1540 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1541 FD_CONNECT|FD_WINE_LISTENING);
1542 return 0;
1543 }
1544
1545 /***********************************************************************
1546 * WSAConnect (WS2_32.30)
1547 */
1548 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1549 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1550 LPQOS lpSQOS, LPQOS lpGQOS )
1551 {
1552 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1553 FIXME("unsupported parameters!\n");
1554 return WS_connect( s, name, namelen );
1555 }
1556
1557
1558 cs130_tom 1.1 /***********************************************************************
1559 * getpeername (WS2_32.5)
1560 */
1561 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1562 {
1563 int fd;
1564 int res;
1565
1566 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1567
1568 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1569 if( (name == NULL) || (namelen == NULL) )
1570 {
1571 SetLastError( WSAEFAULT );
1572 return SOCKET_ERROR;
1573 }
1574
1575 fd = get_sock_fd( s, 0, NULL );
1576 res = SOCKET_ERROR;
1577
1578 if (fd != -1)
1579 cs130_tom 1.1 {
1580 struct sockaddr* uaddr;
1581 int uaddrlen;
1582
1583 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1584 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1585 {
1586 SetLastError(wsaErrno());
1587 }
1588 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1589 {
1590 /* The buffer was too small */
1591 SetLastError(WSAEFAULT);
1592 }
1593 else
1594 {
1595 res=0;
1596 }
1597 ws_sockaddr_free(uaddr,name);
1598 release_sock_fd( s, fd );
1599 }
1600 cs130_tom 1.1 return res;
1601 }
1602
1603 /***********************************************************************
1604 * getsockname (WS2_32.6)
1605 */
1606 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1607 {
1608 int fd;
1609 int res;
1610
1611 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1612
1613 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1614 if( (name == NULL) || (namelen == NULL) )
1615 {
1616 SetLastError( WSAEFAULT );
1617 return SOCKET_ERROR;
1618 }
1619
1620 fd = get_sock_fd( s, 0, NULL );
1621 cs130_tom 1.1 res = SOCKET_ERROR;
1622
1623 if (fd != -1)
1624 {
1625 struct sockaddr* uaddr;
1626 int uaddrlen;
1627
1628 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1629 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1630 {
1631 SetLastError(wsaErrno());
1632 }
1633 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1634 {
1635 /* The buffer was too small */
1636 SetLastError(WSAEFAULT);
1637 }
1638 else
1639 {
1640 res=0;
1641 }
1642 cs130_tom 1.1 ws_sockaddr_free(uaddr,name);
1643 release_sock_fd( s, fd );
1644 }
1645 return res;
1646 }
1647
1648 /***********************************************************************
1649 * getsockopt (WS2_32.7)
1650 */
1651 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1652 INT optname, char *optval, INT *optlen)
1653 {
1654 int fd;
1655 INT ret = 0;
1656
1657 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1658 (int) optname, (int) optval, (int) *optlen);
1659 /* SO_OPENTYPE does not require a valid socket handle. */
1660 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1661 {
1662 if (!optlen || *optlen < sizeof(int) || !optval)
1663 cs130_tom 1.1 {
1664 SetLastError(WSAEFAULT);
1665 return SOCKET_ERROR;
1666 }
1667 *(int *)optval = get_per_thread_data()->opentype;
1668 *optlen = sizeof(int);
1669 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1670 return 0;
1671 }
1672
1673 #ifdef HAVE_IPX
1674 if(level == NSPROTO_IPX)
1675 {
1676 struct WS_sockaddr_ipx addr;
1677 IPX_ADDRESS_DATA *data;
1678 int namelen;
1679 switch(optname)
1680 {
1681 case IPX_PTYPE:
1682 fd = get_sock_fd( s, 0, NULL );
1683 #ifdef SOL_IPX
1684 cs130_tom 1.1 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
1685 {
1686 return SOCKET_ERROR;
1687 }
1688 #else
1689 {
1690 struct ipx val;
1691 socklen_t len=sizeof(struct ipx);
1692
1693 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1694 return SOCKET_ERROR;
1695 *optval = (int)val.ipx_pt;
1696 }
1697 #endif
1698 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1699 release_sock_fd( s, fd );
1700
1701 return 0;
1702 case IPX_ADDRESS:
1703 /*
1704 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1705 cs130_tom 1.1 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1706 * only "one" device active and further it is not possible to query things like the linkspeed.
1707 */
1708 FIXME("IPX_ADDRESS\n");
1709 namelen = sizeof(struct WS_sockaddr);
1710 memset(&addr, 0, sizeof(struct WS_sockaddr));
1711 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1712
1713 data = (IPX_ADDRESS_DATA*)optval;
1714 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1715 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1716 data->adapternum = 0;
1717 data->wan = FALSE; /* We are not on a wan for now .. */
1718 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1719 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1720 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1721 return 0;
1722 case IPX_MAX_ADAPTER_NUM:
1723 FIXME("IPX_MAX_ADAPTER_NUM\n");
1724 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1725
1726 cs130_tom 1.1 return 0;
1727 default:
1728 FIXME("IPX optname:%x\n", optname);
1729 return SOCKET_ERROR;
1730 }
1731 }
1732 #endif
1733
1734 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1735 return SOCKET_ERROR;
1736
1737 if (!convert_sockopt(&level, &optname)) {
1738 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1739 ret = SOCKET_ERROR;
1740 } else {
1741 struct timeval tv;
1742 struct linger lingval;
1743 INT len, *plen = optlen;
1744 char *pval = optval;
1745 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1746 len = sizeof(tv);
1747 cs130_tom 1.1 plen = &len;
1748 pval = (char *) &tv;
1749 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1750 len = sizeof(lingval);
1751 plen = &len;
1752 pval = (char *) &lingval;
1753 }
1754 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1755 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1756 ret = SOCKET_ERROR;
1757 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1758 if( *optlen >= sizeof(INT) ) {
1759 *optlen = sizeof(INT);
1760 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1761 } else {
1762 SetLastError(WSAEFAULT);
1763 ret = SOCKET_ERROR;
1764 }
1765 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1766 if( *optlen >= sizeof( LINGER) ) {
1767 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1768 cs130_tom 1.1 (( LINGER *) optval)->l_linger = lingval.l_linger;
1769 } else {
1770 SetLastError(WSAEFAULT);
1771 ret = SOCKET_ERROR;
1772 }
1773 }
1774 }
1775 release_sock_fd( s, fd );
1776 return ret;
1777 }
1778
1779
1780 /***********************************************************************
1781 * htonl (WINSOCK.8)
1782 * htonl (WS2_32.8)
1783 */
1784 u_long WINAPI WS_htonl(u_long hostlong)
1785 {
1786 return htonl(hostlong);
1787 }
1788
1789 cs130_tom 1.1
1790 /***********************************************************************
1791 * htons (WINSOCK.9)
1792 * htons (WS2_32.9)
1793 */
1794 u_short WINAPI WS_htons(u_short hostshort)
1795 {
1796 return htons(hostshort);
1797 }
1798
1799 /***********************************************************************
1800 * WSAHtonl (WS2_32.46)
1801 * From MSDN decription of error codes, this function should also
1802 * check if WinSock has been initialized and the socket is a valid
1803 * socket. But why? This function only translates a host byte order
1804 * u_long into a network byte order u_long...
1805 */
1806 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1807 {
1808 if (lpnetlong)
1809 {
1810 cs130_tom 1.1 *lpnetlong = htonl(hostlong);
1811 return 0;
1812 }
1813 WSASetLastError(WSAEFAULT);
1814 return SOCKET_ERROR;
1815 }
1816
1817 /***********************************************************************
1818 * WSAHtons (WS2_32.47)
1819 * From MSDN decription of error codes, this function should also
1820 * check if WinSock has been initialized and the socket is a valid
1821 * socket. But why? This function only translates a host byte order
1822 * u_short into a network byte order u_short...
1823 */
1824 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1825 {
1826
1827 if (lpnetshort)
1828 {
1829 *lpnetshort = htons(hostshort);
1830 return 0;
1831 cs130_tom 1.1 }
1832 WSASetLastError(WSAEFAULT);
1833 return SOCKET_ERROR;
1834 }
1835
1836
1837 /***********************************************************************
1838 * inet_addr (WINSOCK.10)
1839 * inet_addr (WS2_32.11)
1840 */
1841 u_long WINAPI WS_inet_addr(const char *cp)
1842 {
1843 return inet_addr(cp);
1844 }
1845
1846
1847 /***********************************************************************
1848 * ntohl (WINSOCK.14)
1849 * ntohl (WS2_32.14)
1850 */
1851 u_long WINAPI WS_ntohl(u_long netlong)
1852 cs130_tom 1.1 {
1853 return ntohl(netlong);
1854 }
1855
1856
1857 /***********************************************************************
1858 * ntohs (WINSOCK.15)
1859 * ntohs (WS2_32.15)
1860 */
1861 u_short WINAPI WS_ntohs(u_short netshort)
1862 {
1863 return ntohs(netshort);
1864 }
1865
1866
1867 /***********************************************************************
1868 * inet_ntoa (WS2_32.12)
1869 */
1870 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1871 {
1872 /* use "buffer for dummies" here because some applications have a
1873 cs130_tom 1.1 * propensity to decode addresses in ws_hostent structure without
1874 * saving them first...
1875 */
1876 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1877
1878 char* s = inet_ntoa(*((struct in_addr*)&in));
1879 if( s )
1880 {
1881 strcpy(dbuffer, s);
1882 return dbuffer;
1883 }
1884 SetLastError(wsaErrno());
1885 return NULL;
1886 }
1887
1888 /**********************************************************************
1889 * WSAIoctl (WS2_32.50)
1890 *
1891 *
1892 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1893 */
1894 cs130_tom 1.1 INT WINAPI WSAIoctl(SOCKET s,
1895 DWORD dwIoControlCode,
1896 LPVOID lpvInBuffer,
1897 DWORD cbInBuffer,
1898 LPVOID lpbOutBuffer,
1899 DWORD cbOutBuffer,
1900 LPDWORD lpcbBytesReturned,
1901 LPWSAOVERLAPPED lpOverlapped,
1902 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1903 {
1904 int fd = get_sock_fd( s, 0, NULL );
1905
1906 if (fd == -1) return SOCKET_ERROR;
1907
1908 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
1909 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1910 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1911
1912 switch( dwIoControlCode )
1913 {
1914 case SIO_GET_INTERFACE_LIST:
1915 cs130_tom 1.1 {
1916 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1917 DWORD size, numInt, apiReturn;
1918
1919 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
1920
1921 if (!lpbOutBuffer)
1922 {
1923 release_sock_fd( s, fd );
1924 WSASetLastError(WSAEFAULT);
1925 return SOCKET_ERROR;
1926 }
1927 if (!lpcbBytesReturned)
1928 {
1929 release_sock_fd( s, fd );
1930 WSASetLastError(WSAEFAULT);
1931 return SOCKET_ERROR;
1932 }
1933
1934 apiReturn = GetAdaptersInfo(NULL, &size);
1935 if (apiReturn == ERROR_NO_DATA)
1936 cs130_tom 1.1 {
1937 numInt = 0;
1938 }
1939 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1940 {
1941 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1942
1943 if (table)
1944 {
1945 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1946 {
1947 PIP_ADAPTER_INFO ptr;
1948
1949 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1950 {
1951 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1952 HeapFree(GetProcessHeap(),0,table);
1953 release_sock_fd( s, fd );
1954 WSASetLastError(WSAEFAULT);
1955 return SOCKET_ERROR;
1956 }
1957 cs130_tom 1.1 for (ptr = table, numInt = 0; ptr;
1958 ptr = ptr->Next, intArray++, numInt++)
1959 {
1960 unsigned int addr, mask, bcast;
1961 struct ifreq ifInfo;
1962
1963 /* Socket Status Flags */
1964 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1965 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1966 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1967 {
1968 ERR("Error obtaining status flags for socket!\n");
1969 HeapFree(GetProcessHeap(),0,table);
1970 release_sock_fd( s, fd );
1971 WSASetLastError(WSAEINVAL);
1972 return SOCKET_ERROR;
1973 }
1974 else
1975 {
1976 /* set flags; the values of IFF_* are not the same
1977 under Linux and Windows, therefore must generate
1978 cs130_tom 1.1 new flags */
1979 intArray->iiFlags = 0;
1980 if (ifInfo.ifr_flags & IFF_BROADCAST)
1981 intArray->iiFlags |= WS_IFF_BROADCAST;
1982 #ifdef IFF_POINTOPOINT
1983 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1984 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1985 #endif
1986 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1987 intArray->iiFlags |= WS_IFF_LOOPBACK;
1988 if (ifInfo.ifr_flags & IFF_UP)
1989 intArray->iiFlags |= WS_IFF_UP;
1990 if (ifInfo.ifr_flags & IFF_MULTICAST)
1991 intArray->iiFlags |= WS_IFF_MULTICAST;
1992 }
1993
1994 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1995 mask = inet_addr(ptr->IpAddressList.IpMask.String);
1996 bcast = addr | (addr & !mask);
1997 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1998 intArray->iiAddress.AddressIn.sin_port = 0;
1999 cs130_tom 1.1 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2000 addr;
2001 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2002 intArray->iiNetmask.AddressIn.sin_port = 0;
2003 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2004 mask;
2005 intArray->iiBroadcastAddress.AddressIn.sin_family =
2006 AF_INET;
2007 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2008 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2009 WS_s_addr = bcast;
2010 }
2011 }
2012 else
2013 {
2014 ERR("Unable to get interface table!\n");
2015 release_sock_fd( s, fd );
2016 HeapFree(GetProcessHeap(),0,table);
2017 WSASetLastError(WSAEINVAL);
2018 return SOCKET_ERROR;
2019 }
2020 cs130_tom 1.1 HeapFree(GetProcessHeap(),0,table);
2021 }
2022 else
2023 {
2024 release_sock_fd( s, fd );
2025 WSASetLastError(WSAEINVAL);
2026 return SOCKET_ERROR;
2027 }
2028 }
2029 else
2030 {
2031 ERR("Unable to get interface table!\n");
2032 release_sock_fd( s, fd );
2033 WSASetLastError(WSAEINVAL);
2034 return SOCKET_ERROR;
2035 }
2036 /* Calculate the size of the array being returned */
2037 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2038 break;
2039 }
2040
2041 cs130_tom 1.1 case SIO_ADDRESS_LIST_CHANGE:
2042 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2043 /* FIXME: error and return code depend on whether socket was created
2044 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2045 break;
2046
2047 default:
2048 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2049 release_sock_fd( s, fd );
2050 WSASetLastError(WSAEOPNOTSUPP);
2051 return SOCKET_ERROR;
2052 }
2053
2054 /* Function executed with no errors */
2055 release_sock_fd( s, fd );
2056 return 0;
2057 }
2058
2059
2060 /***********************************************************************
2061 * ioctlsocket (WS2_32.10)
2062 cs130_tom 1.1 */
2063 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2064 {
2065 int fd;
2066 long newcmd = cmd;
2067
2068 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2069
2070 switch( cmd )
2071 {
2072 case WS_FIONREAD:
2073 newcmd=FIONREAD;
2074 break;
2075
2076 case WS_FIONBIO:
2077 if( _get_sock_mask(s) )
2078 {
2079 /* AsyncSelect()'ed sockets are always nonblocking */
2080 if (*argp) return 0;
2081 SetLastError(WSAEINVAL);
2082 return SOCKET_ERROR;
2083 cs130_tom 1.1 }
2084 fd = get_sock_fd( s, 0, NULL );
2085 if (fd != -1)
2086 {
2087 int ret;
2088 if (*argp)
2089 {
2090 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2091 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2092 }
2093 else
2094 {
2095 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2096 ret = fcntl( fd, F_SETFL, 0 );
2097 }
2098 release_sock_fd( s, fd );
2099 if (!ret) return 0;
2100 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2101 }
2102 return SOCKET_ERROR;
2103
2104 cs130_tom 1.1 case WS_SIOCATMARK:
2105 newcmd=SIOCATMARK;
2106 break;
2107
2108 case WS__IOW('f',125,u_long):
2109 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2110 SetLastError(WSAEINVAL);
2111 return SOCKET_ERROR;
2112
2113 case SIOCGIFBRDADDR:
2114 case SIOCGIFNETMASK:
2115 case SIOCGIFADDR:
2116 /* These don't need any special handling. They are used by
2117 WsControl, and are here to suppress an unnecessary warning. */
2118 break;
2119
2120 default:
2121 /* Netscape tries hard to use bogus ioctl 0x667e */
2122 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2123 break;
2124 }
2125 cs130_tom 1.1
2126 fd = get_sock_fd( s, 0, NULL );
2127 if (fd != -1)
2128 {
2129 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2130 {
2131 release_sock_fd( s, fd );
2132 return 0;
2133 }
2134 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2135 release_sock_fd( s, fd );
2136 }
2137 return SOCKET_ERROR;
2138 }
2139
2140 /***********************************************************************
2141 * listen (WS2_32.13)
2142 */
2143 int WINAPI WS_listen(SOCKET s, int backlog)
2144 {
2145 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2146 cs130_tom 1.1
2147 TRACE("socket %04x, backlog %d\n", s, backlog);
2148 if (fd != -1)
2149 {
2150 if (listen(fd, backlog) == 0)
2151 {
2152 release_sock_fd( s, fd );
2153 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2154 FD_WINE_LISTENING,
2155 FD_CONNECT|FD_WINE_CONNECTED);
2156 return 0;
2157 }
2158 SetLastError(wsaErrno());
2159 release_sock_fd( s, fd );
2160 }
2161 return SOCKET_ERROR;
2162 }
2163
2164 /***********************************************************************
2165 * recv (WS2_32.16)
2166 */
2167 cs130_tom 1.1 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2168 {
2169 DWORD n, dwFlags = flags;
2170 WSABUF wsabuf;
2171
2172 wsabuf.len = len;
2173 wsabuf.buf = buf;
2174
2175 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2176 return SOCKET_ERROR;
2177 else
2178 return n;
2179 }
2180
2181 /***********************************************************************
2182 * recvfrom (WS2_32.17)
2183 */
2184 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2185 struct WS_sockaddr *from, int *fromlen)
2186 {
2187 DWORD n, dwFlags = flags;
2188 cs130_tom 1.1 WSABUF wsabuf;
2189
2190 wsabuf.len = len;
2191 wsabuf.buf = buf;
2192
2193 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2194 return SOCKET_ERROR;
2195 else
2196 return n;
2197 }
2198
2199 /***********************************************************************
2200 * select (WS2_32.18)
2201 */
2202 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2203 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2204 const struct WS_timeval* ws_timeout)
2205 {
2206 int highfd = 0;
2207 fd_set readfds, writefds, exceptfds;
2208 fd_set *p_read, *p_write, *p_except;
2209 cs130_tom 1.1 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2210 struct timeval timeout, *timeoutaddr = NULL;
2211
2212 TRACE("read %p, write %p, excp %p timeout %p\n",
2213 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2214
2215 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2216 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2217 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2218 if (ws_timeout)
2219 {
2220 timeoutaddr = &timeout;
2221 timeout.tv_sec=ws_timeout->tv_sec;
2222 timeout.tv_usec=ws_timeout->tv_usec;
2223 }
2224
2225 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2226 {
2227 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2228 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2229
2230 cs130_tom 1.1 if (p_except && ws_exceptfds)
2231 {
2232 unsigned int i, j;
2233
2234 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2235 {
2236 int fd = exceptfd[i];
2237 SOCKET s = ws_exceptfds->fd_array[i];
2238 if (fd == -1) continue;
2239 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2240 release_sock_fd( s, fd );
2241 }
2242 ws_exceptfds->fd_count = j;
2243 }
2244 return highfd;
2245 }
2246 fd_set_unimport(ws_readfds, readfd);
2247 fd_set_unimport(ws_writefds, writefd);
2248 fd_set_unimport(ws_exceptfds, exceptfd);
2249
2250 if( highfd == 0 ) return 0;
2251 cs130_tom 1.1 SetLastError(wsaErrno());
2252 return SOCKET_ERROR;
2253 }
2254
2255
2256 /***********************************************************************
2257 * send (WS2_32.19)
2258 */
2259 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2260 {
2261 DWORD n;
2262 WSABUF wsabuf;
2263
2264 wsabuf.len = len;
2265 wsabuf.buf = (char*) buf;
2266
2267 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2268 return SOCKET_ERROR;
2269 else
2270 return n;
2271 }
2272 cs130_tom 1.1
2273 /***********************************************************************
2274 * WSASend (WS2_32.72)
2275 */
2276 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2277 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2278 LPWSAOVERLAPPED lpOverlapped,
2279 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2280 {
2281 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2282 NULL, 0, lpOverlapped, lpCompletionRoutine );
2283 }
2284
2285 /***********************************************************************
2286 * WSASendDisconnect (WS2_32.73)
2287 */
2288 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2289 {
2290 return WS_shutdown( s, SD_SEND );
2291 }
2292
2293 cs130_tom 1.1
2294 /***********************************************************************
2295 * WSASendTo (WS2_32.74)
2296 */
2297 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2298 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2299 const struct WS_sockaddr *to, int tolen,
2300 LPWSAOVERLAPPED lpOverlapped,
2301 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2302 {
2303 unsigned int i;
2304 int n, fd, err = WSAENOTSOCK, flags, ret;
2305 struct iovec* iovec;
2306 struct ws2_async *wsa;
2307 IO_STATUS_BLOCK* iosb;
2308
2309 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2310 s, lpBuffers, dwBufferCount, dwFlags,
2311 to, tolen, lpOverlapped, lpCompletionRoutine);
2312
2313 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2314 cs130_tom 1.1 TRACE( "fd=%d, flags=%x\n", fd, flags );
2315
2316 if ( fd == -1 ) return SOCKET_ERROR;
2317
2318 if (flags & FD_FLAG_SEND_SHUTDOWN)
2319 {
2320 WSASetLastError( WSAESHUTDOWN );
2321 goto err_close;
2322 }
2323
2324 if ( !lpNumberOfBytesSent )
2325 {
2326 err = WSAEFAULT;
2327 goto err_close;
2328 }
2329
2330 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2331
2332 if ( !iovec )
2333 {
2334 err = WSAEFAULT;
2335 cs130_tom 1.1 goto err_close;
2336 }
2337
2338 for ( i = 0; i < dwBufferCount; i++ )
2339 {
2340 iovec[i].iov_base = lpBuffers[i].buf;
2341 iovec[i].iov_len = lpBuffers[i].len;
2342 }
2343
2344 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2345 {
2346 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2347 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2348 lpOverlapped, lpCompletionRoutine, &iosb );
2349 if ( !wsa )
2350 {
2351 err = WSAEFAULT;
2352 goto err_free;
2353 }
2354
2355 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2356 cs130_tom 1.1 {
2357 err = NtStatusToWSAError( ret );
2358
2359 if ( !lpOverlapped )
2360 HeapFree( GetProcessHeap(), 0, iosb );
2361 HeapFree( GetProcessHeap(), 0, wsa );
2362 goto err_free;
2363 }
2364
2365 /* Try immediate completion */
2366 if ( lpOverlapped )
2367 {
2368 if ( WSAGetOverlappedResult( s, lpOverlapped,
2369 lpNumberOfBytesSent, FALSE, &dwFlags) )
2370 return 0;
2371
2372 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2373 goto error;
2374 }
2375
2376 WSASetLastError( WSA_IO_PENDING );
2377 cs130_tom 1.1 return SOCKET_ERROR;
2378 }
2379
2380 if (_is_blocking(s))
2381 {
2382 /* FIXME: exceptfds? */
2383 int timeout = GET_SNDTIMEO(fd);
2384 if( !do_block(fd, POLLOUT, timeout)) {
2385 err = WSAETIMEDOUT;
2386 goto err_free; /* msdn says a timeout in send is fatal */
2387 }
2388 }
2389
2390 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2391 if ( n == -1 )
2392 {
2393 err = wsaErrno();
2394 if ( err == WSAEWOULDBLOCK )
2395 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2396 goto err_free;
2397 }
2398 cs130_tom 1.1
2399 TRACE(" -> %i bytes\n", n);
2400 *lpNumberOfBytesSent = n;
2401
2402 HeapFree( GetProcessHeap(), 0, iovec );
2403 release_sock_fd( s, fd );
2404 return 0;
2405
2406 err_free:
2407 HeapFree( GetProcessHeap(), 0, iovec );
2408
2409 err_close:
2410 release_sock_fd( s, fd );
2411
2412 error:
2413 WARN(" -> ERROR %d\n", err);
2414 WSASetLastError(err);
2415 return SOCKET_ERROR;
2416 }
2417
2418 /***********************************************************************
2419 cs130_tom 1.1 * sendto (WS2_32.20)
2420 */
2421 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2422 const struct WS_sockaddr *to, int tolen)
2423 {
2424 DWORD n;
2425 WSABUF wsabuf;
2426
2427 wsabuf.len = len;
2428 wsabuf.buf = (char*) buf;
2429
2430 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2431 return SOCKET_ERROR;
2432 else
2433 return n;
2434 }
2435
2436 /***********************************************************************
2437 * setsockopt (WS2_32.21)
2438 */
2439 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2440 cs130_tom 1.1 const char *optval, int optlen)
2441 {
2442 int fd;
2443 int woptval;
2444 struct linger linger;
2445 struct timeval tval;
2446
2447 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2448 s, level, optname, optval, optlen);
2449
2450 /* SO_OPENTYPE does not require a valid socket handle. */
2451 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2452 {
2453 if (optlen < sizeof(int) || !optval)
2454 {
2455 SetLastError(WSAEFAULT);
2456 return SOCKET_ERROR;
2457 }
2458 get_per_thread_data()->opentype = *(int *)optval;
2459 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2460 return 0;
2461 cs130_tom 1.1 }
2462
2463 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2464 * socket. This will either not happen under windows or it is ignored in
2465 * windows (but it works in linux and therefore prevents the game from
2466 * finding games outside the current network) */
2467 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2468 {
2469 FIXME("Does windows ignore SO_DONTROUTE?\n");
2470 return 0;
2471 }
2472
2473 #ifdef HAVE_IPX
2474 if(level == NSPROTO_IPX)
2475 {
2476 switch(optname)
2477 {
2478 case IPX_PTYPE:
2479 fd = get_sock_fd( s, 0, NULL );
2480 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2481
2482 cs130_tom 1.1 /* We try to set the ipx type on ipx socket level. */
2483 #ifdef SOL_IPX
2484 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2485 {
2486 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2487 return SOCKET_ERROR;
2488 }
2489 #else
2490 {
2491 struct ipx val;
2492 /* Should we retrieve val using a getsockopt call and then
2493 * set the modified one? */
2494 val.ipx_pt = *optval;
2495 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2496 }
2497 #endif
2498 release_sock_fd( s, fd );
2499 return 0;
2500 case IPX_FILTERPTYPE:
2501 /* Sets the receive filter packet type, at the moment we don't support it */
2502 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2503 cs130_tom 1.1
2504 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2505 return 0;
2506 default:
2507 FIXME("opt_name:%x\n", optname);
2508 return SOCKET_ERROR;
2509 }
2510 return 0;
2511 }
2512 #endif
2513
2514 /* Is a privileged and useless operation, so we don't. */
2515 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2516 {
2517 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2518 return 0;
2519 }
2520
2521 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2522 /* This is unique to WinSock and takes special conversion */
2523 linger.l_onoff = *((int*)optval) ? 0: 1;
2524 cs130_tom 1.1 linger.l_linger = 0;
2525 optname=SO_LINGER;
2526 optval = (char*)&linger;
2527 optlen = sizeof(struct linger);
2528 level = SOL_SOCKET;
2529 }
2530 else
2531 {
2532 if (!convert_sockopt(&level, &optname)) {
2533 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2534 SetLastError(WSAENOPROTOOPT);
2535 return SOCKET_ERROR;
2536 }
2537 if (optname == SO_LINGER && optval) {
2538 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2539 linger.l_linger = ((LINGER*)optval)->l_linger;
2540 /* FIXME: what is documented behavior if SO_LINGER optval
2541 is null?? */
2542 optval = (char*)&linger;
2543 optlen = sizeof(struct linger);
2544 }
2545 cs130_tom 1.1 else if (optval && optlen < sizeof(int))
2546 {
2547 woptval= *((INT16 *) optval);
2548 optval= (char*) &woptval;
2549 optlen=sizeof(int);
2550 }
2551 if (level == SOL_SOCKET && is_timeout_option(optname))
2552 {
2553 if (optlen == sizeof(UINT32)) {
2554 /* WinSock passes miliseconds instead of struct timeval */
2555 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2556 tval.tv_sec = *(PUINT32)optval / 1000;
2557 /* min of 500 milisec */
2558 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2559 tval.tv_usec = 500000;
2560 optlen = sizeof(struct timeval);
2561 optval = (char*)&tval;
2562 } else if (optlen == sizeof(struct timeval)) {
2563 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2564 } else {
2565 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2566 cs130_tom 1.1 return 0;
2567 }
2568 }
2569 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2570 {
2571 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2572 return 0;
2573 }
2574 }
2575
2576
2577 fd = get_sock_fd( s, 0, NULL );
2578 if (fd == -1) return SOCKET_ERROR;
2579
2580 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2581 {
2582 release_sock_fd( s, fd );
2583 return 0;
2584 }
2585 TRACE("Setting socket error, %d\n", wsaErrno());
2586 SetLastError(wsaErrno());
2587 cs130_tom 1.1 release_sock_fd( s, fd );
2588 return SOCKET_ERROR;
2589 }
2590
2591 /***********************************************************************
2592 * shutdown (WS2_32.22)
2593 */
2594 int WINAPI WS_shutdown(SOCKET s, int how)
2595 {
2596 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2597 unsigned int clear_flags = 0;
2598
2599 fd = get_sock_fd( s, 0, &flags );
2600 TRACE("socket %04x, how %i %x\n", s, how, flags );
2601
2602 if (fd == -1)
2603 return SOCKET_ERROR;
2604
2605 switch( how )
2606 {
2607 case 0: /* drop receives */
2608 cs130_tom 1.1 clear_flags |= FD_READ;
2609 break;
2610 case 1: /* drop sends */
2611 clear_flags |= FD_WRITE;
2612 break;
2613 case 2: /* drop all */
2614 clear_flags |= FD_READ|FD_WRITE;
2615 default:
2616 clear_flags |= FD_WINE_LISTENING;
2617 }
2618
2619 if ( flags & FD_FLAG_OVERLAPPED ) {
2620
2621 switch ( how )
2622 {
2623 case SD_RECEIVE:
2624 fd0 = fd;
2625 break;
2626 case SD_SEND:
2627 fd1 = fd;
2628 break;
2629 cs130_tom 1.1 case SD_BOTH:
2630 default:
2631 fd0 = fd;
2632 fd1 = get_sock_fd( s, 0, NULL );
2633 break;
2634 }
2635
2636 if ( fd0 != -1 )
2637 {
2638 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2639 if ( err )
2640 {
2641 release_sock_fd( s, fd0 );
2642 goto error;
2643 }
2644 }
2645 if ( fd1 != -1 )
2646 {
2647 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2648 if ( err )
2649 {
2650 cs130_tom 1.1 release_sock_fd( s, fd1 );
2651 goto error;
2652 }
2653 }
2654 }
2655 else /* non-overlapped mode */
2656 {
2657 if ( shutdown( fd, how ) )
2658 {
2659 err = wsaErrno();
2660 release_sock_fd( s, fd );
2661 goto error;
2662 }
2663 release_sock_fd( s, fd );
2664 }
2665
2666 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2667 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2668 return 0;
2669
2670 error:
2671 cs130_tom 1.1 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2672 WSASetLastError( err );
2673 return SOCKET_ERROR;
2674 }
2675
2676 /***********************************************************************
2677 * socket (WS2_32.23)
2678 */
2679 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2680 {
2681 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2682
2683 return WSASocketA( af, type, protocol, NULL, 0,
2684 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2685 }
2686
2687
2688 /***********************************************************************
2689 * gethostbyaddr (WS2_32.51)
2690 */
2691 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2692 cs130_tom 1.1 {
2693 struct WS_hostent *retval = NULL;
2694 struct hostent* host;
2695
2696 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2697 char *extrabuf;
2698 int ebufsize=1024;
2699 struct hostent hostentry;
2700 int locerr=ENOBUFS;
2701 host = NULL;
2702 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2703 while(extrabuf) {
2704 int res = gethostbyaddr_r(addr, len, type,
2705 &hostentry, extrabuf, ebufsize, &host, &locerr);
2706 if( res != ERANGE) break;
2707 ebufsize *=2;
2708 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2709 }
2710 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2711 #else
2712 EnterCriticalSection( &csWSgetXXXbyYYY );
2713 cs130_tom 1.1 host = gethostbyaddr(addr, len, type);
2714 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2715 #endif
2716 if( host != NULL ) retval = WS_dup_he(host);
2717 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2718 HeapFree(GetProcessHeap(),0,extrabuf);
2719 #else
2720 LeaveCriticalSection( &csWSgetXXXbyYYY );
2721 #endif
2722 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2723 return retval;
2724 }
2725
2726 /***********************************************************************
2727 * gethostbyname (WS2_32.52)
2728 */
2729 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2730 {
2731 struct WS_hostent *retval = NULL;
2732 struct hostent* host;
2733 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2734 cs130_tom 1.1 char *extrabuf;
2735 int ebufsize=1024;
2736 struct hostent hostentry;
2737 int locerr = ENOBUFS;
2738 #endif
2739 char buf[100];
2740 if( !name) {
2741 name = buf;
2742 if( gethostname( buf, 100) == -1) {
2743 SetLastError( WSAENOBUFS); /* appropriate ? */
2744 return retval;
2745 }
2746 }
2747 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2748 host = NULL;
2749 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2750 while(extrabuf) {
2751 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2752 if( res != ERANGE) break;
2753 ebufsize *=2;
2754 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2755 cs130_tom 1.1 }
2756 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2757 #else
2758 EnterCriticalSection( &csWSgetXXXbyYYY );
2759 host = gethostbyname(name);
2760 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2761 #endif
2762 if (host) retval = WS_dup_he(host);
2763 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2764 HeapFree(GetProcessHeap(),0,extrabuf);
2765 #else
2766 LeaveCriticalSection( &csWSgetXXXbyYYY );
2767 #endif
2768 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2769 return retval;
2770 }
2771
2772
2773 /***********************************************************************
2774 * getprotobyname (WS2_32.53)
2775 */
2776 cs130_tom 1.1 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2777 {
2778 struct WS_protoent* retval = NULL;
2779 #ifdef HAVE_GETPROTOBYNAME
2780 struct protoent* proto;
2781 EnterCriticalSection( &csWSgetXXXbyYYY );
2782 if( (proto = getprotobyname(name)) != NULL )
2783 {
2784 retval = WS_dup_pe(proto);
2785 }
2786 else {
2787 MESSAGE("protocol %s not found; You might want to add "
2788 "this to /etc/protocols\n", debugstr_a(name) );
2789 SetLastError(WSANO_DATA);
2790 }
2791 LeaveCriticalSection( &csWSgetXXXbyYYY );
2792 #endif
2793 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2794 return retval;
2795 }
2796
2797 cs130_tom 1.1
2798 /***********************************************************************
2799 * getprotobynumber (WS2_32.54)
2800 */
2801 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2802 {
2803 struct WS_protoent* retval = NULL;
2804 #ifdef HAVE_GETPROTOBYNUMBER
2805 struct protoent* proto;
2806 EnterCriticalSection( &csWSgetXXXbyYYY );
2807 if( (proto = getprotobynumber(number)) != NULL )
2808 {
2809 retval = WS_dup_pe(proto);
2810 }
2811 else {
2812 MESSAGE("protocol number %d not found; You might want to add "
2813 "this to /etc/protocols\n", number );
2814 SetLastError(WSANO_DATA);
2815 }
2816 LeaveCriticalSection( &csWSgetXXXbyYYY );
2817 #endif
2818 cs130_tom 1.1 TRACE("%i ret %p\n", number, retval);
2819 return retval;
2820 }
2821
2822
2823 /***********************************************************************
2824 * getservbyname (WS2_32.55)
2825 */
2826 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2827 {
2828 struct WS_servent* retval = NULL;
2829 struct servent* serv;
2830 char *name_str;
2831 char *proto_str = NULL;
2832
2833 if (!(name_str = strdup_lower(name))) return NULL;
2834
2835 if (proto && *proto)
2836 {
2837 if (!(proto_str = strdup_lower(proto)))
2838 {
2839 cs130_tom 1.1 HeapFree( GetProcessHeap(), 0, name_str );
2840 return NULL;
2841 }
2842 }
2843
2844 EnterCriticalSection( &csWSgetXXXbyYYY );
2845 serv = getservbyname(name_str, proto_str);
2846 if( serv != NULL )
2847 {
2848 retval = WS_dup_se(serv);
2849 }
2850 else SetLastError(WSANO_DATA);
2851 LeaveCriticalSection( &csWSgetXXXbyYYY );
2852 HeapFree( GetProcessHeap(), 0, proto_str );
2853 HeapFree( GetProcessHeap(), 0, name_str );
2854 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2855 return retval;
2856 }
2857
2858
2859 /***********************************************************************
2860 cs130_tom 1.1 * getservbyport (WS2_32.56)
2861 */
2862 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2863 {
2864 struct WS_servent* retval = NULL;
2865 #ifdef HAVE_GETSERVBYPORT
2866 struct servent* serv;
2867 char *proto_str = NULL;
2868
2869 if (proto && *proto)
2870 {
2871 if (!(proto_str = strdup_lower(proto))) return NULL;
2872 }
2873 EnterCriticalSection( &csWSgetXXXbyYYY );
2874 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2875 retval = WS_dup_se(serv);
2876 }
2877 else SetLastError(WSANO_DATA);
2878 LeaveCriticalSection( &csWSgetXXXbyYYY );
2879 HeapFree( GetProcessHeap(), 0, proto_str );
2880 #endif
2881 cs130_tom 1.1 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2882 return retval;
2883 }
2884
2885
2886 /***********************************************************************
2887 * gethostname (WS2_32.57)
2888 */
2889 int WINAPI WS_gethostname(char *name, int namelen)
2890 {
2891 TRACE("name %p, len %d\n", name, namelen);
2892
2893 if (gethostname(name, namelen) == 0)
2894 {
2895 TRACE("<- '%s'\n", name);
2896 return 0;
2897 }
2898 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2899 TRACE("<- ERROR !\n");
2900 return SOCKET_ERROR;
2901 }
2902 cs130_tom 1.1
2903
2904 /* ------------------------------------- Windows sockets extensions -- *
2905 * *
2906 * ------------------------------------------------------------------- */
2907
2908 /***********************************************************************
2909 * WSAEnumNetworkEvents (WS2_32.36)
2910 */
2911 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2912 {
2913 int ret;
2914
2915 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2916
2917 SERVER_START_REQ( get_socket_event )
2918 {
2919 req->handle = SOCKET2HANDLE(s);
2920 req->service = TRUE;
2921 req->c_event = hEvent;
2922 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2923 cs130_tom 1.1 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2924 }
2925 SERVER_END_REQ;
2926 if (!ret) return 0;
2927 SetLastError(WSAEINVAL);
2928 return SOCKET_ERROR;
2929 }
2930
2931 /***********************************************************************
2932 * WSAEventSelect (WS2_32.39)
2933 */
2934 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2935 {
2936 int ret;
2937
2938 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2939
2940 SERVER_START_REQ( set_socket_event )
2941 {
2942 req->handle = SOCKET2HANDLE(s);
2943 req->mask = lEvent;
2944 cs130_tom 1.1 req->event = hEvent;
2945 req->window = 0;
2946 req->msg = 0;
2947 ret = wine_server_call( req );
2948 }
2949 SERVER_END_REQ;
2950 if (!ret) return 0;
2951 SetLastError(WSAEINVAL);
2952 return SOCKET_ERROR;
2953 }
2954
2955 /**********************************************************************
2956 * WSAGetOverlappedResult (WS2_32.40)
2957 */
2958 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2959 LPDWORD lpcbTransfer, BOOL fWait,
2960 LPDWORD lpdwFlags )
2961 {
2962 DWORD r;
2963
2964 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2965 cs130_tom 1.1 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2966
2967 if ( lpOverlapped == NULL )
2968 {
2969 ERR( "Invalid pointer\n" );
2970 WSASetLastError(WSA_INVALID_PARAMETER);
2971 return FALSE;
2972 }
2973
2974 if ( fWait )
2975 {
2976 if (lpOverlapped->hEvent)
2977 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
2978 INFINITE, TRUE) == STATUS_USER_APC );
2979 else /* busy loop */
2980 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
2981 Sleep( 10 );
2982
2983 }
2984 else if ( lpOverlapped->Internal == STATUS_PENDING )
2985 {
2986 cs130_tom 1.1 /* Wait in order to give APCs a chance to run. */
2987 /* This is cheating, so we must set the event again in case of success -
2988 it may be a non-manual reset event. */
2989 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2990 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
2991 NtSetEvent( lpOverlapped->hEvent, NULL );
2992 }
2993
2994 if ( lpcbTransfer )
2995 *lpcbTransfer = lpOverlapped->InternalHigh;
2996
2997 if ( lpdwFlags )
2998 *lpdwFlags = lpOverlapped->Offset;
2999
3000 switch ( lpOverlapped->Internal )
3001 {
3002 case STATUS_SUCCESS:
3003 return TRUE;
3004 case STATUS_PENDING:
3005 WSASetLastError( WSA_IO_INCOMPLETE );
3006 if (fWait) ERR("PENDING status after waiting!\n");
3007 cs130_tom 1.1 return FALSE;
3008 default:
3009 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3010 return FALSE;
3011 }
3012 }
3013
3014
3015 /***********************************************************************
3016 * WSAAsyncSelect (WS2_32.101)
3017 */
3018 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3019 {
3020 int ret;
3021
3022 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3023
3024 SERVER_START_REQ( set_socket_event )
3025 {
3026 req->handle = SOCKET2HANDLE(s);
3027 req->mask = lEvent;
3028 cs130_tom 1.1 req->event = 0;
3029 req->window = hWnd;
3030 req->msg = uMsg;
3031 ret = wine_server_call( req );
3032 }
3033 SERVER_END_REQ;
3034 if (!ret) return 0;
3035 SetLastError(WSAEINVAL);
3036 return SOCKET_ERROR;
3037 }
3038
3039 /***********************************************************************
3040 * WSACreateEvent (WS2_32.31)
3041 *
3042 */
3043 WSAEVENT WINAPI WSACreateEvent(void)
3044 {
3045 /* Create a manual-reset event, with initial state: unsignaled */
3046 TRACE("\n");
3047
3048 return CreateEventW(NULL, TRUE, FALSE, NULL);
3049 cs130_tom 1.1 }
3050
3051 /***********************************************************************
3052 * WSACloseEvent (WS2_32.29)
3053 *
3054 */
3055 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3056 {
3057 TRACE ("event=%p\n", event);
3058
3059 return CloseHandle(event);
3060 }
3061
3062 /***********************************************************************
3063 * WSASocketA (WS2_32.78)
3064 *
3065 */
3066 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3067 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3068 GROUP g, DWORD dwFlags)
3069 {
3070 cs130_tom 1.1 INT len;
3071 WSAPROTOCOL_INFOW info;
3072
3073 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3074 af, type, protocol, lpProtocolInfo, g, dwFlags);
3075
3076 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3077
3078 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3079 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3080 info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3081
3082 if (!len)
3083 {
3084 WSASetLastError( WSAEINVAL);
3085 return SOCKET_ERROR;
3086 }
3087
3088 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3089 }
3090
3091 cs130_tom 1.1 /***********************************************************************
3092 * WSASocketW (WS2_32.79)
3093 *
3094 */
3095 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3096 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3097 GROUP g, DWORD dwFlags)
3098 {
3099 SOCKET ret;
3100
3101 /*
3102 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3103 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3104 */
3105
3106 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3107 af, type, protocol, lpProtocolInfo, g, dwFlags );
3108
3109 /* hack for WSADuplicateSocket */
3110 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3111 ret = lpProtocolInfo->dwCatalogEntryId;
3112 cs130_tom 1.1 TRACE("\tgot duplicate %04x\n", ret);
3113 return ret;
3114 }
3115
3116 /* check the socket family */
3117 switch(af)
3118 {
3119 #ifdef HAVE_IPX
3120 case WS_AF_IPX: af = AF_IPX;
3121 #endif
3122 case AF_INET:
3123 case AF_UNSPEC:
3124 break;
3125 default:
3126 SetLastError(WSAEAFNOSUPPORT);
3127 return INVALID_SOCKET;
3128 }
3129
3130 /* check the socket type */
3131 switch(type)
3132 {
3133 cs130_tom 1.1 case WS_SOCK_STREAM:
3134 type=SOCK_STREAM;
3135 break;
3136 case WS_SOCK_DGRAM:
3137 type=SOCK_DGRAM;
3138 break;
3139 case WS_SOCK_RAW:
3140 type=SOCK_RAW;
3141 break;
3142 default:
3143 SetLastError(WSAESOCKTNOSUPPORT);
3144 return INVALID_SOCKET;
3145 }
3146
3147 /* check the protocol type */
3148 if ( protocol < 0 ) /* don't support negative values */
3149 {
3150 SetLastError(WSAEPROTONOSUPPORT);
3151 return INVALID_SOCKET;
3152 }
3153
3154 cs130_tom 1.1 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3155 switch(protocol)
3156 {
3157 case IPPROTO_TCP:
3158 if (type == SOCK_STREAM) { af = AF_INET; break; }
3159 case IPPROTO_UDP:
3160 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3161 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3162 }
3163
3164 SERVER_START_REQ( create_socket )
3165 {
3166 req->family = af;
3167 req->type = type;
3168 req->protocol = protocol;
3169 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3170 req->flags = dwFlags;
3171 req->inherit = TRUE;
3172 set_error( wine_server_call( req ) );
3173 ret = HANDLE2SOCKET( reply->handle );
3174 }
3175 cs130_tom 1.1 SERVER_END_REQ;
3176 if (ret)
3177 {
3178 TRACE("\tcreated %04x\n", ret );
3179 return ret;
3180 }
3181
3182 if (GetLastError() == WSAEACCES) /* raw socket denied */
3183 {
3184 if (type == SOCK_RAW)
3185 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3186 else
3187 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3188 SetLastError(WSAESOCKTNOSUPPORT);
3189 }
3190
3191 WARN("\t\tfailed!\n");
3192 return INVALID_SOCKET;
3193 }
3194
3195 /***********************************************************************
3196 cs130_tom 1.1 * WSAJoinLeaf (WS2_32.58)
3197 *
3198 */
3199 SOCKET WINAPI WSAJoinLeaf(
3200 SOCKET s,
3201 const struct WS_sockaddr *addr,
3202 int addrlen,
3203 LPWSABUF lpCallerData,
3204 LPWSABUF lpCalleeData,
3205 LPQOS lpSQOS,
3206 LPQOS lpGQOS,
3207 DWORD dwFlags)
3208 {
3209 FIXME("stub.\n");
3210 return INVALID_SOCKET;
3211 }
3212
3213 /***********************************************************************
3214 * __WSAFDIsSet (WS2_32.151)
3215 */
3216 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3217 cs130_tom 1.1 {
3218 int i = set->fd_count;
3219
3220 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3221
3222 while (i--)
3223 if (set->fd_array[i] == s) return 1;
3224 return 0;
3225 }
3226
3227 /***********************************************************************
3228 * WSAIsBlocking (WINSOCK.114)
3229 * WSAIsBlocking (WS2_32.114)
3230 */
3231 BOOL WINAPI WSAIsBlocking(void)
3232 {
3233 /* By default WinSock should set all its sockets to non-blocking mode
3234 * and poll in PeekMessage loop when processing "blocking" ones. This
3235 * function is supposed to tell if the program is in this loop. Our
3236 * blocking calls are truly blocking so we always return FALSE.
3237 *
3238 cs130_tom 1.1 * Note: It is allowed to call this function without prior WSAStartup().
3239 */
3240
3241 TRACE("\n");
3242 return FALSE;
3243 }
3244
3245 /***********************************************************************
3246 * WSACancelBlockingCall (WINSOCK.113)
3247 * WSACancelBlockingCall (WS2_32.113)
3248 */
3249 INT WINAPI WSACancelBlockingCall(void)
3250 {
3251 TRACE("\n");
3252 return 0;
3253 }
3254
3255 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3256 {
3257 FIXME("How was this called?\n");
3258 return x();
3259 cs130_tom 1.1 }
3260
3261
3262 /***********************************************************************
3263 * WSASetBlockingHook (WS2_32.109)
3264 */
3265 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3266 {
3267 FARPROC prev = blocking_hook;
3268 blocking_hook = lpBlockFunc;
3269 TRACE("hook %p\n", lpBlockFunc);
3270 return prev;
3271 }
3272
3273
3274 /***********************************************************************
3275 * WSAUnhookBlockingHook (WS2_32.110)
3276 */
3277 INT WINAPI WSAUnhookBlockingHook(void)
3278 {
3279 blocking_hook = WSA_DefaultBlockingHook;
3280 cs130_tom 1.1 return 0;
3281 }
3282
3283
3284 /* ----------------------------------- end of API stuff */
3285
3286 /* ----------------------------------- helper functions -
3287 *
3288 * TODO: Merge WS_dup_..() stuff into one function that
3289 * would operate with a generic structure containing internal
3290 * pointers (via a template of some kind).
3291 */
3292
3293 static int list_size(char** l, int item_size)
3294 {
3295 int i,j = 0;
3296 if(l)
3297 { for(i=0;l[i];i++)
3298 j += (item_size) ? item_size : strlen(l[i]) + 1;
3299 j += (i + 1) * sizeof(char*); }
3300 return j;
3301 cs130_tom 1.1 }
3302
3303 static int list_dup(char** l_src, char** l_to, int item_size)
3304 {
3305 char *p;
3306 int i;
3307
3308 for (i = 0; l_src[i]; i++) ;
3309 p = (char *)(l_to + i + 1);
3310 for (i = 0; l_src[i]; i++)
3311 {
3312 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3313 memcpy(p, l_src[i], count);
3314 l_to[i] = p;
3315 p += count;
3316 }
3317 l_to[i] = NULL;
3318 return p - (char *)l_to;
3319 }
3320
3321 /* ----- hostent */
3322 cs130_tom 1.1
3323 /* duplicate hostent entry
3324 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3325 * Dito for protoent and servent.
3326 */
3327 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3328 {
3329 char *p;
3330 struct WS_hostent *p_to;
3331
3332 int size = (sizeof(*p_he) +
3333 strlen(p_he->h_name) + 1 +
3334 list_size(p_he->h_aliases, 0) +
3335 list_size(p_he->h_addr_list, p_he->h_length));
3336
3337 if (!(p_to = check_buffer_he(size))) return NULL;
3338 p_to->h_addrtype = p_he->h_addrtype;
3339 p_to->h_length = p_he->h_length;
3340
3341 p = (char *)(p_to + 1);
3342 p_to->h_name = p;
3343 cs130_tom 1.1 strcpy(p, p_he->h_name);
3344 p += strlen(p) + 1;
3345
3346 p_to->h_aliases = (char **)p;
3347 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3348
3349 p_to->h_addr_list = (char **)p;
3350 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3351 return p_to;
3352 }
3353
3354 /* ----- protoent */
3355
3356 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3357 {
3358 char *p;
3359 struct WS_protoent *p_to;
3360
3361 int size = (sizeof(*p_pe) +
3362 strlen(p_pe->p_name) + 1 +
3363 list_size(p_pe->p_aliases, 0));
3364 cs130_tom 1.1
3365 if (!(p_to = check_buffer_pe(size))) return NULL;
3366 p_to->p_proto = p_pe->p_proto;
3367
3368 p = (char *)(p_to + 1);
3369 p_to->p_name = p;
3370 strcpy(p, p_pe->p_name);
3371 p += strlen(p) + 1;
3372
3373 p_to->p_aliases = (char **)p;
3374 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3375 return p_to;
3376 }
3377
3378 /* ----- servent */
3379
3380 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3381 {
3382 char *p;
|
3404 cs130_tom 1.1 }
3405
3406 /* ----------------------------------- error handling */
3407
3408 UINT wsaErrno(void)
3409 {
3410 int loc_errno = errno;
3411 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3412
3413 switch(loc_errno)
3414 {
3415 case EINTR: return WSAEINTR;
3416 case EBADF: return WSAEBADF;
3417 case EPERM:
3418 case EACCES: return WSAEACCES;
3419 case EFAULT: return WSAEFAULT;
3420 case EINVAL: return WSAEINVAL;
3421 case EMFILE: return WSAEMFILE;
3422 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3423 case EINPROGRESS: return WSAEINPROGRESS;
3424 case EALREADY: return WSAEALREADY;
3425 cs130_tom 1.1 case ENOTSOCK: return WSAENOTSOCK;
3426 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3427 case EMSGSIZE: return WSAEMSGSIZE;
3428 case EPROTOTYPE: return WSAEPROTOTYPE;
3429 case ENOPROTOOPT: return WSAENOPROTOOPT;
3430 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3431 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3432 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3433 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3434 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3435 case EADDRINUSE: return WSAEADDRINUSE;
3436 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3437 case ENETDOWN: return WSAENETDOWN;
3438 case ENETUNREACH: return WSAENETUNREACH;
3439 case ENETRESET: return WSAENETRESET;
3440 case ECONNABORTED: return WSAECONNABORTED;
3441 case EPIPE:
3442 case ECONNRESET: return WSAECONNRESET;
3443 case ENOBUFS: return WSAENOBUFS;
3444 case EISCONN: return WSAEISCONN;
3445 case ENOTCONN: return WSAENOTCONN;
3446 cs130_tom 1.1 case ESHUTDOWN: return WSAESHUTDOWN;
3447 case ETOOMANYREFS: return WSAETOOMANYREFS;
3448 case ETIMEDOUT: return WSAETIMEDOUT;
3449 case ECONNREFUSED: return WSAECONNREFUSED;
3450 case ELOOP: return WSAELOOP;
3451 case ENAMETOOLONG: return WSAENAMETOOLONG;
3452 case EHOSTDOWN: return WSAEHOSTDOWN;
3453 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3454 case ENOTEMPTY: return WSAENOTEMPTY;
3455 #ifdef EPROCLIM
3456 case EPROCLIM: return WSAEPROCLIM;
3457 #endif
3458 #ifdef EUSERS
3459 case EUSERS: return WSAEUSERS;
3460 #endif
3461 #ifdef EDQUOT
3462 case EDQUOT: return WSAEDQUOT;
3463 #endif
3464 #ifdef ESTALE
3465 case ESTALE: return WSAESTALE;
3466 #endif
3467 cs130_tom 1.1 #ifdef EREMOTE
3468 case EREMOTE: return WSAEREMOTE;
3469 #endif
3470
3471 /* just in case we ever get here and there are no problems */
3472 case 0: return 0;
3473 default:
3474 WARN("Unknown errno %d!\n", loc_errno);
3475 return WSAEOPNOTSUPP;
3476 }
3477 }
3478
3479 UINT wsaHerrno(int loc_errno)
3480 {
3481
3482 WARN("h_errno %d.\n", loc_errno);
3483
3484 switch(loc_errno)
3485 {
3486 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3487 case TRY_AGAIN: return WSATRY_AGAIN;
3488 cs130_tom 1.1 case NO_RECOVERY: return WSANO_RECOVERY;
3489 case NO_DATA: return WSANO_DATA;
3490 case ENOBUFS: return WSAENOBUFS;
3491
3492 case 0: return 0;
3493 default:
3494 WARN("Unknown h_errno %d!\n", loc_errno);
3495 return WSAEOPNOTSUPP;
3496 }
3497 }
3498
3499
3500 /***********************************************************************
3501 * WSARecv (WS2_32.67)
3502 */
3503 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3504 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3505 LPWSAOVERLAPPED lpOverlapped,
3506 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3507 {
3508 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3509 cs130_tom 1.1 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3510 }
3511
3512 /***********************************************************************
3513 * WSARecvFrom (WS2_32.69)
3514 */
3515 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3516 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3517 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3518 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3519
3520 {
3521 unsigned int i;
3522 int n, fd, err = WSAENOTSOCK, flags, ret;
3523 struct iovec* iovec;
3524 struct ws2_async *wsa;
3525 IO_STATUS_BLOCK* iosb;
3526
3527 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3528 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3529 (lpFromlen ? *lpFromlen : -1L),
3530 cs130_tom 1.1 lpOverlapped, lpCompletionRoutine);
3531
3532 fd = get_sock_fd( s, GENERIC_READ, &flags );
3533 TRACE( "fd=%d, flags=%x\n", fd, flags );
3534
3535 if (fd == -1) return SOCKET_ERROR;
3536
3537 if (flags & FD_FLAG_RECV_SHUTDOWN)
3538 {
3539 WSASetLastError( WSAESHUTDOWN );
3540 goto err_close;
3541 }
3542
3543 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3544 if ( !iovec )
3545 {
3546 err = WSAEFAULT;
3547 goto err_close;
3548 }
3549
3550 for (i = 0; i < dwBufferCount; i++)
3551 cs130_tom 1.1 {
3552 iovec[i].iov_base = lpBuffers[i].buf;
3553 iovec[i].iov_len = lpBuffers[i].len;
3554 }
3555
3556 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3557 {
3558 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3559 lpFlags, lpFrom, lpFromlen,
3560 lpOverlapped, lpCompletionRoutine, &iosb );
3561
3562 if ( !wsa )
3563 {
3564 err = WSAEFAULT;
3565 goto err_free;
3566 }
3567
3568 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3569 {
3570 err = NtStatusToWSAError( ret );
3571
3572 cs130_tom 1.1 if ( !lpOverlapped )
3573 HeapFree( GetProcessHeap(), 0, iosb );
3574 HeapFree( GetProcessHeap(), 0, wsa );
3575 goto err_free;
3576 }
3577
3578 /* Try immediate completion */
3579 if ( lpOverlapped )
3580 {
3581 if ( WSAGetOverlappedResult( s, lpOverlapped,
3582 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3583 return 0;
3584
3585 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3586 goto error;
3587 }
3588
3589 WSASetLastError( WSA_IO_PENDING );
3590 return SOCKET_ERROR;
3591 }
3592
3593 cs130_tom 1.1 if ( _is_blocking(s) )
3594 {
3595 /* block here */
3596 /* FIXME: OOB and exceptfds? */
3597 int timeout = GET_RCVTIMEO(fd);
3598 if( !do_block(fd, POLLIN, timeout)) {
3599 err = WSAETIMEDOUT;
3600 /* a timeout is not fatal */
3601 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3602 goto err_free;
3603 }
3604 }
3605
3606 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3607 if ( n == -1 )
3608 {
3609 err = wsaErrno();
3610 goto err_free;
3611 }
3612
3613 TRACE(" -> %i bytes\n", n);
3614 cs130_tom 1.1 *lpNumberOfBytesRecvd = n;
3615
3616 HeapFree(GetProcessHeap(), 0, iovec);
3617 release_sock_fd( s, fd );
3618 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3619
3620 return 0;
3621
3622 err_free:
3623 HeapFree(GetProcessHeap(), 0, iovec);
3624
3625 err_close:
3626 release_sock_fd( s, fd );
3627
3628 error:
3629 WARN(" -> ERROR %d\n", err);
3630 WSASetLastError( err );
3631 return SOCKET_ERROR;
3632 }
3633
3634 /***********************************************************************
3635 cs130_tom 1.1 * WSCInstallProvider (WS2_32.88)
3636 */
3637 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3638 LPCWSTR lpszProviderDllPath,
3639 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3640 DWORD dwNumberOfEntries,
3641 LPINT lpErrno )
3642 {
3643 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3644 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3645 dwNumberOfEntries, lpErrno);
3646 *lpErrno = 0;
3647 return 0;
3648 }
3649
3650
3651 /***********************************************************************
3652 * WSCDeinstallProvider (WS2_32.83)
3653 */
3654 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3655 {
3656 cs130_tom 1.1 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3657 *lpErrno = 0;
3658 return 0;
3659 }
3660
3661
3662 /***********************************************************************
3663 * WSAAccept (WS2_32.26)
3664 */
3665 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3666 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3667 {
3668
3669 int ret = 0, size = 0;
3670 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3671 /* QOS SQOS, GQOS; */
3672 GROUP g;
3673 SOCKET cs;
3674 SOCKADDR src_addr, dst_addr;
3675
3676 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3677 cs130_tom 1.1 s, addr, addrlen, lpfnCondition, dwCallbackData);
3678
3679
3680 size = sizeof(src_addr);
3681 cs = WS_accept(s, &src_addr, &size);
3682
3683 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3684
3685 CallerId.buf = (char *)&src_addr;
3686 CallerId.len = sizeof(src_addr);
3687
3688 CallerData.buf = NULL;
3689 CallerData.len = (ULONG)NULL;
3690
3691 WS_getsockname(cs, &dst_addr, &size);
3692
3693 CalleeId.buf = (char *)&dst_addr;
3694 CalleeId.len = sizeof(dst_addr);
3695
3696
3697 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3698 cs130_tom 1.1 &CalleeId, &CalleeData, &g, dwCallbackData);
3699
3700 switch (ret)
3701 {
3702 case CF_ACCEPT:
3703 if (addr && addrlen)
3704 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3705 return cs;
3706 case CF_DEFER:
3707 SERVER_START_REQ( set_socket_deferred )
3708 {
3709 req->handle = SOCKET2HANDLE(s);
3710 req->deferred = SOCKET2HANDLE(cs);
3711 if ( !wine_server_call_err ( req ) )
3712 {
3713 SetLastError( WSATRY_AGAIN );
3714 WS_closesocket( cs );
3715 }
3716 }
3717 SERVER_END_REQ;
3718 return SOCKET_ERROR;
3719 cs130_tom 1.1 case CF_REJECT:
3720 WS_closesocket(cs);
3721 SetLastError(WSAECONNREFUSED);
3722 return SOCKET_ERROR;
3723 default:
3724 FIXME("Unknown return type from Condition function\n");
3725 SetLastError(WSAENOTSOCK);
3726 return SOCKET_ERROR;
3727 }
3728 }
3729
3730 /***********************************************************************
3731 * WSADuplicateSocketA (WS2_32.32)
3732 */
3733 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3734 {
3735 HANDLE hProcess;
3736
3737 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3738 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3739 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3740 cs130_tom 1.1 /* I don't know what the real Windoze does next, this is a hack */
3741 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3742 * the target use the global duplicate, or we could copy a reference to us to the structure
3743 * and let the target duplicate it from us, but let's do it as simple as possible */
3744 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3745 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3746 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3747 0, FALSE, DUPLICATE_SAME_ACCESS);
3748 CloseHandle(hProcess);
3749 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3750 return 0;
3751 }
3752
3753 /***********************************************************************
3754 * WSADuplicateSocketW (WS2_32.33)
3755 */
3756 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3757 {
3758 HANDLE hProcess;
3759
3760 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3761 cs130_tom 1.1
3762 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3763 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3764 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3765 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3766 0, FALSE, DUPLICATE_SAME_ACCESS);
3767 CloseHandle(hProcess);
3768 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3769 return 0;
3770 }
3771
3772 /***********************************************************************
3773 * WSAInstallServiceClassA (WS2_32.48)
3774 */
3775 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3776 {
3777 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3778 WSASetLastError(WSAEACCES);
3779 return SOCKET_ERROR;
3780 }
3781
3782 cs130_tom 1.1 /***********************************************************************
3783 * WSAInstallServiceClassW (WS2_32.49)
3784 */
3785 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3786 {
3787 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3788 WSASetLastError(WSAEACCES);
3789 return SOCKET_ERROR;
3790 }
3791
3792 /***********************************************************************
3793 * WSARemoveServiceClass (WS2_32.70)
3794 */
3795 int WINAPI WSARemoveServiceClass(LPGUID info)
3796 {
3797 FIXME("Request to remove service %p\n",info);
3798 WSASetLastError(WSATYPE_NOT_FOUND);
3799 return SOCKET_ERROR;
3800 }
3801
3802 /***********************************************************************
3803 cs130_tom 1.1 * WSAStringToAddressA (WS2_32.80)
3804 */
3805 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3806 INT AddressFamily,
3807 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3808 LPSOCKADDR lpAddress,
3809 LPINT lpAddressLength)
3810 {
3811 INT res=0;
3812 LONG inetaddr;
3813 LPSTR workBuffer=NULL,ptrPort;
3814
3815 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3816 lpAddress, lpAddressLength );
3817
3818 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3819
3820 if (AddressString)
3821 {
3822 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3823 if (workBuffer)
3824 cs130_tom 1.1 {
3825 strcpy(workBuffer,AddressString);
3826 switch (AddressFamily)
3827 {
3828 case AF_INET:
3829 /* caller wants to know the size of the socket buffer */
3830 if (*lpAddressLength < sizeof(SOCKADDR_IN))
3831 {
3832 *lpAddressLength = sizeof(SOCKADDR_IN);
3833 res = WSAEFAULT;
3834 }
3835 else
3836 {
3837 /* caller wants to translate an AdressString into a SOCKADDR */
3838 if (lpAddress)
3839 {
3840 memset(lpAddress,0,sizeof(SOCKADDR_IN));
3841 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3842 ptrPort = strchr(workBuffer,':');
3843 if (ptrPort)
3844 {
3845 cs130_tom 1.1 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3846 *ptrPort = '\0';
3847 }
3848 else
3849 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3850 inetaddr = inet_addr(workBuffer);
3851 if (inetaddr != INADDR_NONE)
3852 {
3853 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
3854 res = 0;
3855 }
3856 else
3857 res = WSAEINVAL;
3858 }
3859 }
3860 if (lpProtocolInfo)
3861 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3862 AddressString, AddressFamily,
3863 lpProtocolInfo, lpAddress, lpAddressLength);
3864
3865 break;
3866 cs130_tom 1.1 default:
3867 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3868 AddressString, AddressFamily,
3869 lpProtocolInfo, lpAddress, lpAddressLength);
3870 }
3871 HeapFree( GetProcessHeap(), 0, workBuffer );
3872 }
3873 else
3874 res = WSA_NOT_ENOUGH_MEMORY;
3875 }
3876 else
3877 res = WSAEINVAL;
3878
3879 if (!res) return 0;
3880 WSASetLastError(res);
3881 return SOCKET_ERROR;
3882 }
3883
3884 /***********************************************************************
3885 * WSAStringToAddressW (WS2_32.81)
3886 *
3887 cs130_tom 1.1 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3888 * If this should be the case, it would be required to map these digits
3889 * to Unicode digits (0-9) using FoldString first.
3890 */
3891 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3892 INT AddressFamily,
3893 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3894 LPSOCKADDR lpAddress,
3895 LPINT lpAddressLength)
3896 {
3897 INT sBuffer,res=0;
3898 LPSTR workBuffer=NULL;
3899 WSAPROTOCOL_INFOA infoA;
3900 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3901
3902 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3903 lpAddress, lpAddressLength );
3904
3905 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3906
3907 /* if ProtocolInfo is available - convert to ANSI variant */
3908 cs130_tom 1.1 if (lpProtocolInfo)
3909 {
3910 lpProtoInfoA = &infoA;
3911 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3912
3913 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3914 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3915 {
3916 WSASetLastError( WSAEINVAL);
3917 return SOCKET_ERROR;
3918 }
3919 }
3920
3921 if (AddressString)
3922 {
3923 /* Translate AddressString to ANSI code page - assumes that only
3924 standard digits 0-9 are used with this API call */
3925 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3926 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3927
3928 if (workBuffer)
3929 cs130_tom 1.1 {
3930 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3931 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3932 lpAddress,lpAddressLength);
3933 HeapFree( GetProcessHeap(), 0, workBuffer );
3934 return res;
3935 }
3936 else
3937 res = WSA_NOT_ENOUGH_MEMORY;
3938 }
3939 else
3940 res = WSAEINVAL;
3941
3942 WSASetLastError(res);
3943 return SOCKET_ERROR;
3944 }
3945
3946 /***********************************************************************
3947 * WSAAddressToStringA (WS2_32.27)
3948 *
3949 * See WSAAddressToStringW
3950 cs130_tom 1.1 */
3951 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3952 LPWSAPROTOCOL_INFOA info, LPSTR string,
3953 LPDWORD lenstr )
3954 {
3955 INT size;
3956 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3957 CHAR *p;
3958
3959 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3960
3961 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3962 if (!string || !lenstr) return SOCKET_ERROR;
3963
3964 /* sin_family is garanteed to be the first u_short */
3965 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3966
3967 sprintf( buffer, "%u.%u.%u.%u:%u",
3968 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3969 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3970 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3971 cs130_tom 1.1 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3972 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3973
3974 p = strchr( buffer, ':' );
3975 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3976
3977 size = strlen( buffer );
3978
3979 if (*lenstr < size)
3980 {
3981 *lenstr = size;
3982 return SOCKET_ERROR;
3983 }
3984
3985 strcpy( string, buffer );
3986 return 0;
3987 }
3988
3989 /***********************************************************************
3990 * WSAAddressToStringW (WS2_32.28)
3991 *
3992 cs130_tom 1.1 * Convert a sockaddr address into a readable address string.
3993 *
3994 * PARAMS
3995 * sockaddr [I] Pointer to a sockaddr structure.
3996 * len [I] Size of the sockaddr structure.
3997 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
3998 * string [I/O] Pointer to a buffer to receive the address string.
3999 * lenstr [I/O] Size of the receive buffer in WCHARs.
4000 *
4001 * RETURNS
4002 * Success: 0
4003 * Failure: SOCKET_ERROR
4004 *
4005 * NOTES
4006 * The 'info' parameter is ignored.
4007 *
4008 * BUGS
4009 * Only supports AF_INET addresses.
4010 */
4011 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4012 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4013 cs130_tom 1.1 LPDWORD lenstr )
4014 {
4015 INT size;
4016 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4017 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4018 WCHAR *p;
4019
4020 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4021
4022 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4023 if (!string || !lenstr) return SOCKET_ERROR;
4024
4025 /* sin_family is garanteed to be the first u_short */
4026 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4027
4028 sprintfW( buffer, format,
4029 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4030 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4031 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4032 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4033 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4034 cs130_tom 1.1
4035 p = strchrW( buffer, ':' );
4036 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4037
4038 size = lstrlenW( buffer );
4039
4040 if (*lenstr < size)
4041 {
4042 *lenstr = size;
4043 return SOCKET_ERROR;
4044 }
4045
4046 lstrcpyW( string, buffer );
4047 return 0;
4048 }
4049
4050 /***********************************************************************
4051 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4052 */
4053 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4054 {
4055 cs130_tom 1.1 FIXME( "(%p %p) Stub!\n", len, buffer );
4056 return 0;
4057 }
4058
4059 /***********************************************************************
4060 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4061 */
4062 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4063 {
4064 FIXME( "(%p %p) Stub!\n", len, buffer );
4065 return 0;
4066 }
4067
4068 /***********************************************************************
4069 * WSAGetQOSByName (WS2_32.41)
4070 */
4071 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4072 {
4073 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4074 return FALSE;
4075 }
4076 cs130_tom 1.1
4077 /***********************************************************************
4078 * WSAGetServiceClassInfoA (WS2_32.42)
4079 */
4080 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4081 LPWSASERVICECLASSINFOA info )
4082 {
4083 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4084 len, info );
4085 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4086 return SOCKET_ERROR;
4087 }
4088
4089 /***********************************************************************
4090 * WSAGetServiceClassInfoW (WS2_32.43)
4091 */
4092 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4093 LPWSASERVICECLASSINFOW info )
4094 {
4095 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4096 len, info );
4097 cs130_tom 1.1 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4098 return SOCKET_ERROR;
4099 }
4100
4101 /***********************************************************************
4102 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4103 */
4104 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4105 {
4106 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4107 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4108 return SOCKET_ERROR;
4109 }
4110
4111 /***********************************************************************
4112 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4113 */
4114 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4115 {
4116 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4117 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4118 cs130_tom 1.1 return SOCKET_ERROR;
4119 }
4120
4121 /***********************************************************************
4122 * WSALookupServiceBeginA (WS2_32.59)
4123 */
4124 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4125 DWORD dwControlFlags,
4126 LPHANDLE lphLookup)
4127 {
4128 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4129 lphLookup);
4130 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4131 return SOCKET_ERROR;
4132 }
4133
4134 /***********************************************************************
4135 * WSALookupServiceBeginW (WS2_32.60)
4136 */
4137 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4138 DWORD dwControlFlags,
4139 cs130_tom 1.1 LPHANDLE lphLookup)
4140 {
4141 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4142 lphLookup);
4143 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4144 return SOCKET_ERROR;
4145 }
4146
4147 /***********************************************************************
4148 * WSALookupServiceBeginW (WS2_32.61)
4149 */
4150 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4151 {
4152 FIXME("(%p) Stub!\n", lookup );
4153 return 0;
4154 }
4155
4156 /***********************************************************************
4157 * WSALookupServiceNextA (WS2_32.62)
4158 */
4159 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4160 cs130_tom 1.1 {
4161 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4162 return 0;
4163 }
4164
4165 /***********************************************************************
4166 * WSALookupServiceNextW (WS2_32.63)
4167 */
4168 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4169 {
4170 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4171 return 0;
4172 }
4173
4174 /***********************************************************************
4175 * WSANtohl (WS2_32.64)
4176 */
4177 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4178 {
4179 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4180
4181 cs130_tom 1.1 if (!lphostlong) return WSAEFAULT;
4182
4183 *lphostlong = ntohl( netlong );
4184 return 0;
4185 }
4186
4187 /***********************************************************************
4188 * WSANtohs (WS2_32.65)
4189 */
4190 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4191 {
4192 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4193
4194 if (!lphostshort) return WSAEFAULT;
4195
4196 *lphostshort = ntohs( netshort );
4197 return 0;
4198 }
4199
4200 /***********************************************************************
4201 * WSAProviderConfigChange (WS2_32.66)
4202 cs130_tom 1.1 */
4203 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4204 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4205 {
4206 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4207 return SOCKET_ERROR;
4208 }
4209
4210 /***********************************************************************
4211 * WSARecvDisconnect (WS2_32.68)
4212 */
4213 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4214 {
4215 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4216
4217 return WS_shutdown( s, 0 );
4218 }
4219
4220 /***********************************************************************
4221 * WSASetServiceA (WS2_32.76)
4222 */
4223 cs130_tom 1.1 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4224 {
4225 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4226 return 0;
4227 }
4228
4229 /***********************************************************************
4230 * WSASetServiceW (WS2_32.77)
4231 */
4232 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4233 {
4234 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4235 return 0;
4236 }
4237
4238 /***********************************************************************
4239 * WSCEnableNSProvider (WS2_32.84)
4240 */
4241 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4242 {
4243 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4244 cs130_tom 1.1 return 0;
4245 }
4246
4247 /***********************************************************************
4248 * WSCGetProviderPath (WS2_32.86)
4249 */
4250 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errno )
4251 {
4252 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errno );
4253
4254 if (!errno || !provider || !len) return WSAEFAULT;
4255
4256 *errno = WSAEINVAL;
4257 return SOCKET_ERROR;
4258 }
4259
4260 /***********************************************************************
4261 * WSCInstallNameSpace (WS2_32.87)
4262 */
4263 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4264 DWORD version, LPGUID provider )
4265 cs130_tom 1.1 {
4266 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4267 namespace, version, debugstr_guid(provider) );
4268 return 0;
4269 }
4270
4271 /***********************************************************************
4272 * WSCUnInstallNameSpace (WS2_32.89)
4273 */
4274 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4275 {
4276 FIXME("(%p) Stub!\n", lpProviderId);
4277 return NO_ERROR;
4278 }
4279
4280 /***********************************************************************
4281 * WSCWriteProviderOrder (WS2_32.91)
4282 */
4283 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4284 {
4285 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4286 cs130_tom 1.1 return 0;
4287 }
|