ReactOS  0.4.13-dev-544-gede3fdd
sockctrl.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS WinSock 2 API
4  * FILE: dll/win32/ws2_32_new/src/sockctrl.c
5  * PURPOSE: Socket Control/State Support
6  * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 /*
19  * @implemented
20  */
21 INT
22 WSAAPI
24  IN CONST struct sockaddr *name,
25  IN INT namelen)
26 {
29  PWSSOCKET Socket;
30  INT ErrorCode, OldErrorCode = ERROR_SUCCESS;
31  INT Status;
33  DPRINT("connect: %lx, %p, %lx\n", s, name, namelen);
34 
35  /* Enter prolog */
37  if (ErrorCode == ERROR_SUCCESS)
38  {
39  /* Get the Socket Context */
40  if ((Socket = WsSockGetSocket(s)))
41  {
42  if (!IsBadReadPtr(name, sizeof(struct sockaddr)))
43  {
44  while (TRUE)
45  {
46  /* Make the call */
48  name,
49  namelen,
50  NULL,
51  NULL,
52  NULL,
53  NULL,
54  &ErrorCode);
55 
56  /* Check if error code was due to the host not being found */
57  if ((Status == SOCKET_ERROR) &&
58  ((ErrorCode == WSAEHOSTUNREACH) ||
60  {
61  /* Check if we can try again */
62  if (TryAgain)
63  {
64  /* Save the old error code */
65  OldErrorCode = ErrorCode;
66 
67  /* Make sure we don't retry 3 times */
68  TryAgain = FALSE;
69 
70  /* Make the RAS Auto-dial attempt */
71  if (WSAttemptAutodialAddr(name, namelen)) continue;
72  }
73  else
74  {
75  /* Restore the error code */
76  ErrorCode = OldErrorCode;
77  }
78  }
79 
80  /* Break out of the loop */
81  break;
82  }
83 
84  /* Deference the Socket Context */
85  WsSockDereference(Socket);
86 
87  /* Return Provider Value */
88  if (Status == ERROR_SUCCESS) return Status;
89 
90  /* If everything seemed fine, then the WSP call failed itself */
92  }
93  else
94  {
95  /* Invalid user pointer */
97  }
98  }
99  else
100  {
101  /* No Socket Context Found */
103  }
104  }
105 
106  /* If this is Winsock 1.1, normalize the error code */
107  if ((ErrorCode == WSAEALREADY) && (LOBYTE(Process->Version) == 1))
108  {
109  /* WS 1.1 apps expect this */
111  }
112 
113  /* Return with an Error */
115  return SOCKET_ERROR;
116 }
117 
118 /*
119  * @implemented
120  */
121 INT
122 WSAAPI
124  IN INT backlog)
125 {
126  PWSSOCKET Socket;
127  INT Status;
128  INT ErrorCode;
129  DPRINT("connect: %lx, %lx\n", s, backlog);
130 
131  /* Check for WSAStartup */
133  {
134  /* Get the Socket Context */
135  if ((Socket = WsSockGetSocket(s)))
136  {
137  /* Make the call */
138  Status = Socket->Provider->Service.lpWSPListen(s,
139  backlog,
140  &ErrorCode);
141  /* Deference the Socket Context */
142  WsSockDereference(Socket);
143 
144  /* Return Provider Value */
145  if (Status == ERROR_SUCCESS) return Status;
146 
147  /* If everything seemed fine, then the WSP call failed itself */
149  }
150  else
151  {
152  /* No Socket Context Found */
154  }
155  }
156 
157  /* Return with an Error */
159  return SOCKET_ERROR;
160 }
161 
162 /*
163  * @implemented
164  */
165 INT
166 WSAAPI
169  IN OUT INT FAR* namelen)
170 {
171  PWSSOCKET Socket;
172  INT Status;
173  INT ErrorCode;
174  DPRINT("getpeername: %lx, %p, %lx\n", s, name, namelen);
175 
176  /* Check for WSAStartup */
178  {
179  /* Get the Socket Context */
180  if ((Socket = WsSockGetSocket(s)))
181  {
182  /* Make the call */
184  name,
185  namelen,
186  &ErrorCode);
187  /* Deference the Socket Context */
188  WsSockDereference(Socket);
189 
190  /* Return Provider Value */
191  if (Status == ERROR_SUCCESS) return Status;
192 
193  /* If everything seemed fine, then the WSP call failed itself */
195  }
196  else
197  {
198  /* No Socket Context Found */
200  }
201  }
202 
203  /* Return with an Error */
205  return SOCKET_ERROR;
206 }
207 
208 /*
209  * @implemented
210  */
211 INT
212 WSAAPI
215  IN OUT INT FAR* namelen)
216 {
217  PWSSOCKET Socket;
218  INT Status;
219  INT ErrorCode;
220  DPRINT("getsockname: %lx, %p, %lx\n", s, name, namelen);
221 
222  /* Check for WSAStartup */
224  {
225  /* Get the Socket Context */
226  if ((Socket = WsSockGetSocket(s)))
227  {
228  if (name && namelen && (*namelen >= sizeof(*name)))
229  {
230  /* Make the call */
232  name,
233  namelen,
234  &ErrorCode);
235 
236  /* Deference the Socket Context */
237  WsSockDereference(Socket);
238 
239  /* Return Provider Value */
240  if (Status == ERROR_SUCCESS) return Status;
241 
242  /* If everything seemed fine, then the WSP call failed itself */
244  }
245  else
246  {
247  /* Deference the Socket Context */
248  WsSockDereference(Socket);
249 
250  /* name or namelen not valid */
252  }
253  }
254  else
255  {
256  /* No Socket Context Found */
258  }
259  }
260 
261  /* Return with an Error */
263  return SOCKET_ERROR;
264 }
265 
266 /*
267  * @implemented
268  */
269 INT
270 WSAAPI
272  IN INT level,
273  IN INT optname,
274  OUT CHAR FAR* optval,
275  IN OUT INT FAR* optlen)
276 {
279  PWSSOCKET Socket;
280  INT ErrorCode;
281  INT Status;
282  WSAPROTOCOL_INFOW ProtocolInfo;
283  PCHAR OldOptVal = NULL;
284  INT OldOptLen = 0;
285  DPRINT("getsockopt: %lx, %lx, %lx\n", s, level, optname);
286 
287  /* Enter prolog */
289  {
290  /* Check if we're getting the open type */
291  if ((level == SOL_SOCKET) && (optname == SO_OPENTYPE))
292  {
293  /* Validate size */
295  _SEH2_TRY
296  {
297  if (!(optlen) || (*optlen < sizeof(DWORD)))
298  {
299  /* Fail */
302  _SEH2_LEAVE;
303  }
304 
305  /* Set the open type */
306  *(DWORD*)optval = Thread->OpenType;
307  *optlen = sizeof(DWORD);
308  }
310  {
313  }
314  _SEH2_END;
315 
316  return Status;
317  }
318 
319  /* Get the Socket Context */
320  if ((Socket = WsSockGetSocket(s)))
321  {
322  /* Check if ANSI data was requested */
323  if ((level == SOL_SOCKET) && (optname == SO_PROTOCOL_INFOA))
324  {
325  /* Validate size and pointers */
327  _SEH2_TRY
328  {
329  if (!(optval) ||
330  !(optlen) ||
331  (*optlen < sizeof(WSAPROTOCOL_INFOA)))
332  {
333  /* Set return size and error code */
334  *optlen = sizeof(WSAPROTOCOL_INFOA);
336  _SEH2_LEAVE;
337  }
338 
339  /* It worked. Save the values */
340  OldOptLen = *optlen;
341  OldOptVal = optval;
342 
343  /* Hack them so WSP will know how to deal with it */
344  *optlen = sizeof(WSAPROTOCOL_INFOW);
345  optval = (PCHAR)&ProtocolInfo;
346  optname = SO_PROTOCOL_INFOW;
347  }
349  {
351  }
352  _SEH2_END;
353 
354  /* Did we encounter invalid parameters? */
355  if (ErrorCode != NO_ERROR)
356  {
357  /* Dereference the socket and fail */
358  WsSockDereference(Socket);
360  return SOCKET_ERROR;
361  }
362  }
363 
364  /* Make the call */
366  level,
367  optname,
368  optval,
369  optlen,
370  &ErrorCode);
371 
372  /* Deference the Socket Context */
373  WsSockDereference(Socket);
374 
375  /* Check provider value */
376  if (Status == ERROR_SUCCESS)
377  {
378  /* Did we use the A->W hack? */
379  if (!OldOptVal) return Status;
380 
381  /* We did, so we have to convert the unicode info to ansi */
382  ErrorCode = MapUnicodeProtocolInfoToAnsi(&ProtocolInfo,
384  OldOptVal);
385 
386  /* Return the length */
387  _SEH2_TRY
388  {
389  *optlen = OldOptLen;
390  }
392  {
394  }
395  _SEH2_END;
396 
397  /* Return success if this worked */
398  if (ErrorCode == ERROR_SUCCESS) return Status;
399  }
400 
401  /* If everything seemed fine, then the WSP call failed itself */
403  }
404  else
405  {
406  /* No Socket Context Found */
408  }
409  }
410 
411  /* Return with an Error */
413  return SOCKET_ERROR;
414 }
415 
416 /*
417  * @implemented
418  */
419 INT
420 WSAAPI
422  IN INT level,
423  IN INT optname,
424  IN CONST CHAR FAR* optval,
425  IN INT optlen)
426 {
429  PWSSOCKET Socket;
430  INT ErrorCode;
431  INT Status;
432  DPRINT("setsockopt: %lx, %lx, %lx\n", s, level, optname);
433 
434  /* Enter prolog */
436  {
437  /* Check if we're changing the open type */
438  if (level == SOL_SOCKET && optname == SO_OPENTYPE)
439  {
440  /* Validate size */
441  if (optlen < sizeof(DWORD))
442  {
443  /* Fail */
445  return SOCKET_ERROR;
446  }
447 
448  /* Set the open type */
450  _SEH2_TRY
451  {
452  Thread->OpenType = *(DWORD*)optval;
453  }
455  {
458  }
459  _SEH2_END;
460 
461  return Status;
462  }
463  if (!optval && optlen > 0)
464  {
466  return SOCKET_ERROR;
467  }
468 
469  /* Get the Socket Context */
470  if ((Socket = WsSockGetSocket(s)))
471  {
472  /* Make the call */
474  level,
475  optname,
476  optval,
477  optlen,
478  &ErrorCode);
479 
480  /* Deference the Socket Context */
481  WsSockDereference(Socket);
482 
483  /* Return Provider Value */
484  if (Status == ERROR_SUCCESS) return Status;
485 
486  /* If everything seemed fine, then the WSP call failed itself */
488  }
489  else
490  {
491  /* No Socket Context Found */
493  }
494  }
495 
496  /* Return with an Error */
498  return SOCKET_ERROR;
499 }
500 
501 /*
502  * @implemented
503  */
504 INT
505 WSAAPI
507  IN INT how)
508 {
509  PWSSOCKET Socket;
510  INT Status;
511  INT ErrorCode;
512  DPRINT("shutdown: %lx, %lx\n", s, how);
513 
514  /* Check for WSAStartup */
516  {
517  /* Get the Socket Context */
518  if ((Socket = WsSockGetSocket(s)))
519  {
520  /* Make the call */
521  Status = Socket->Provider->Service.lpWSPShutdown(s, how, &ErrorCode);
522 
523  /* Deference the Socket Context */
524  WsSockDereference(Socket);
525 
526  /* Return Provider Value */
527  if (Status == ERROR_SUCCESS) return Status;
528 
529  /* If everything seemed fine, then the WSP call failed itself */
531  }
532  else
533  {
534  /* No Socket Context Found */
536  }
537  }
538 
539  /* Return with an Error */
541  return SOCKET_ERROR;
542 }
543 
544 /*
545  * @implemented
546  */
547 INT
548 WSAAPI
550  IN CONST struct sockaddr *name,
551  IN INT namelen,
552  IN LPWSABUF lpCallerData,
553  OUT LPWSABUF lpCalleeData,
554  IN LPQOS lpSQOS,
555  IN LPQOS lpGQOS)
556 {
557  PWSSOCKET Socket;
558  INT Status;
559  INT ErrorCode;
560  DPRINT("WSAConnect: %lx, %lx, %lx, %p\n", s, name, namelen, lpCallerData);
561 
562  /* Check for WSAStartup */
564  {
565  /* Get the Socket Context */
566  if ((Socket = WsSockGetSocket(s)))
567  {
568  /* Make the call */
569  Status = Socket->Provider->Service.lpWSPConnect(s,
570  name,
571  namelen,
572  lpCallerData,
573  lpCalleeData,
574  lpSQOS,
575  lpGQOS,
576  &ErrorCode);
577  /* Deference the Socket Context */
578  WsSockDereference(Socket);
579 
580  /* Return Provider Value */
581  if (Status == ERROR_SUCCESS) return Status;
582 
583  /* If everything seemed fine, then the WSP call failed itself */
585  }
586  else
587  {
588  /* No Socket Context Found */
590  }
591  }
592 
593  /* Return with an Error */
595  return SOCKET_ERROR;
596 }
597 
598 /*
599  * @implemented
600  */
601 BOOL
602 WSAAPI
605  OUT LPDWORD lpcbTransfer,
606  IN BOOL fWait,
607  OUT LPDWORD lpdwFlags)
608 {
609  PWSSOCKET Socket;
610  INT Status;
611  INT ErrorCode;
612  DPRINT("WSAGetOverlappedResult: %lx, %lx\n", s, lpOverlapped);
613 
614  /* Check for WSAStartup */
616  {
617  /* Get the Socket Context */
618  if ((Socket = WsSockGetSocket(s)))
619  {
620  /* Make the call */
622  lpOverlapped,
623  lpcbTransfer,
624  fWait,
625  lpdwFlags,
626  &ErrorCode);
627  /* Deference the Socket Context */
628  WsSockDereference(Socket);
629 
630  /* Return Provider Value */
631  if (Status) return Status;
632  }
633  else
634  {
635  /* No Socket Context Found */
637  }
638  }
639 
640  /* Return with an Error */
642  return FALSE;
643 }
#define WSAENOTSOCK
Definition: winerror.h:1951
signed char * PCHAR
Definition: retypes.h:7
#define SOCKET_ERROR
Definition: winsock.h:333
GLint level
Definition: gl.h:1546
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define WSAEFAULT
Definition: winerror.h:1945
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#define ERROR_SUCCESS
Definition: deptool.c:10
LPWSPSETSOCKOPT lpWSPSetSockOpt
Definition: ws2spi.h:487
#define LOBYTE(W)
Definition: jmemdos.c:487
#define WSAEINVAL
Definition: winerror.h:1946
char CHAR
Definition: xmlstorage.h:175
LPWSPLISTEN lpWSPListen
Definition: ws2spi.h:479
#define SO_PROTOCOL_INFOW
Definition: winsock2.h:249
PWSSOCKET WSAAPI WsSockGetSocket(IN SOCKET Handle)
Definition: dsocket.c:140
#define SOL_SOCKET
Definition: winsock.h:398
BOOL WSAAPI WSAGetOverlappedResult(IN SOCKET s, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpcbTransfer, IN BOOL fWait, OUT LPDWORD lpdwFlags)
Definition: sockctrl.c:603
#define NO_ERROR
Definition: dderror.h:5
GLint namelen
Definition: glext.h:7232
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
int32_t INT
Definition: typedefs.h:56
WSPPROC_TABLE Service
Definition: ws2_32p.h:80
_SEH2_TRY
Definition: create.c:4250
VOID WSAAPI WsSockDereference(IN PWSSOCKET Socket)
Definition: dsocket.c:205
LPWSPCONNECT lpWSPConnect
Definition: ws2spi.h:468
LPWSPSHUTDOWN lpWSPShutdown
Definition: ws2spi.h:488
unsigned int BOOL
Definition: ntddk_ex.h:94
#define FAR
Definition: guiddef.h:36
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
struct _WSAPROTOCOL_INFOW WSAPROTOCOL_INFOW
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
Definition: bl.h:897
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define SO_PROTOCOL_INFOA
Definition: winsock2.h:248
BOOL WINAPI WSAttemptAutodialAddr(IN CONST SOCKADDR FAR *Name, IN INT NameLength)
Definition: winsock.c:20
INT WSAAPI getpeername(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:167
#define PCHAR
Definition: match.c:90
#define WSAEALREADY
Definition: winerror.h:1950
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
PTPROVIDER Provider
Definition: ws2_32p.h:199
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WSAEHOSTUNREACH
Definition: winerror.h:1978
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define SetLastError(x)
Definition: compat.h:409
INT WSAAPI WsApiProlog(OUT PWSPROCESS *Process, OUT PWSTHREAD *Thread)
Definition: wsautil.c:91
#define WSAENETUNREACH
Definition: winerror.h:1964
GLdouble s
Definition: gl.h:2039
LPWSPGETSOCKOPT lpWSPGetSockOpt
Definition: ws2spi.h:475
LPWSPGETOVERLAPPEDRESULT lpWSPGetOverlappedResult
Definition: ws2spi.h:472
Status
Definition: gdiplustypes.h:24
INT WSAAPI getsockopt(IN SOCKET s, IN INT level, IN INT optname, OUT CHAR FAR *optval, IN OUT INT FAR *optlen)
Definition: sockctrl.c:271
#define WSASYSCALLFAILURE
Definition: winerror.h:1994
struct _WSAPROTOCOL_INFOA WSAPROTOCOL_INFOA
_SEH2_END
Definition: create.c:4424
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:90
#define SO_OPENTYPE
Definition: ws2_32.h:40
INT WSAAPI WSAConnect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen, IN LPWSABUF lpCallerData, OUT LPWSABUF lpCalleeData, IN LPQOS lpSQOS, IN LPQOS lpGQOS)
Definition: sockctrl.c:549
#define WSAAPI
Definition: winsock2.h:584
INT WSAAPI MapUnicodeProtocolInfoToAnsi(IN LPWSAPROTOCOL_INFOW UnicodeInfo, OUT LPWSAPROTOCOL_INFOA AnsiInfo)
Definition: wsautil.c:224
LPWSPGETSOCKNAME lpWSPGetSockName
Definition: ws2spi.h:474
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:807
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
Definition: name.c:36
#define OUT
Definition: typedefs.h:39
LPWSPGETPEERNAME lpWSPGetPeerName
Definition: ws2spi.h:473
uint32_t * LPDWORD
Definition: typedefs.h:57
UINT_PTR SOCKET
Definition: winsock.h:47
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_LEAVE
Definition: filesup.c:20
FORCEINLINE DWORD WsQuickProlog(VOID)
Definition: ws2_32p.h:892
INT WSAAPI getsockname(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:213
#define CONST
Definition: pedump.c:81