1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32/src/socklife.c
5 * PURPOSE: Socket Lifetime 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 SOCKET
22 WSAAPI
accept(IN SOCKET s,OUT LPSOCKADDR addr,OUT INT FAR * addrlen)23 accept(IN SOCKET s,
24 OUT LPSOCKADDR addr,
25 OUT INT FAR* addrlen)
26 {
27 /* Let WSA do it */
28 return WSAAccept(s, addr, addrlen, NULL, 0);
29 }
30
31 /*
32 * @implemented
33 */
34 INT
35 WSAAPI
bind(IN SOCKET s,IN CONST struct sockaddr * name,IN INT namelen)36 bind(IN SOCKET s,
37 IN CONST struct sockaddr *name,
38 IN INT namelen)
39 {
40 PWSSOCKET Socket;
41 INT Status;
42 INT ErrorCode;
43 DPRINT("bind: %lx, %p, %lx\n", s, name, namelen);
44
45 /* Check for WSAStartup */
46 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
47 {
48 /* Get the Socket Context */
49 if ((Socket = WsSockGetSocket(s)))
50 {
51 if (name && (namelen >= sizeof(*name)))
52 {
53 /* Make the call */
54 Status = Socket->Provider->Service.lpWSPBind(s,
55 name,
56 namelen,
57 &ErrorCode);
58 /* Deference the Socket Context */
59 WsSockDereference(Socket);
60
61 /* Return Provider Value */
62 if (Status == ERROR_SUCCESS) return Status;
63
64 /* If everything seemed fine, then the WSP call failed itself */
65 if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
66 }
67 else
68 {
69 /* Deference the Socket Context */
70 WsSockDereference(Socket);
71
72 /* name or namelen not valid */
73 ErrorCode = WSAEFAULT;
74 }
75 }
76 else
77 {
78 /* No Socket Context Found */
79 ErrorCode = WSAENOTSOCK;
80 }
81 }
82
83 /* Return with an Error */
84 SetLastError(ErrorCode);
85 return SOCKET_ERROR;
86 }
87
88 /*
89 * @implemented
90 */
91 INT
92 WSAAPI
closesocket(IN SOCKET s)93 closesocket(IN SOCKET s)
94 {
95 PWSSOCKET Socket;
96 INT Status;
97 INT ErrorCode;
98 DPRINT("closesocket: %lx\n", s);
99
100 /* Check for WSAStartup */
101 if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
102 {
103 /* Get the Socket Context */
104 if ((Socket = WsSockGetSocket(s)))
105 {
106 /* Make the call */
107 Status = Socket->Provider->Service.lpWSPCloseSocket(s, &ErrorCode);
108
109 /* Check if this is a provider socket */
110 if ((Status == ERROR_SUCCESS) && (Socket->IsProvider))
111 {
112 /* Disassociate the handle */
113 if (WsSockDisassociateHandle(Socket) == ERROR_SUCCESS)
114 {
115 /* Deference the Socket Context */
116 WsSockDereference(Socket);
117 }
118
119 /* Remove the last reference */
120 WsSockDereference(Socket);
121
122 /* Return success if everything is OK */
123 if (ErrorCode == ERROR_SUCCESS) return ErrorCode;
124 }
125 }
126 else
127 {
128 /* No Socket Context Found */
129 ErrorCode = WSAENOTSOCK;
130 }
131 }
132
133 /* Return with an Error */
134 SetLastError(ErrorCode);
135 return SOCKET_ERROR;
136 }
137
138 /*
139 * @implemented
140 */
141 SOCKET
142 WSAAPI
socket(IN INT af,IN INT type,IN INT protocol)143 socket(IN INT af,
144 IN INT type,
145 IN INT protocol)
146 {
147 PWSPROCESS Process;
148 PWSTHREAD Thread;
149 DWORD Flags = 0;
150 INT ErrorCode;
151 DPRINT("socket: %lx, %lx, %lx\n", af, type, protocol);
152
153 /* Enter prolog */
154 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
155 {
156 /* Fail here */
157 SetLastError(ErrorCode);
158 return INVALID_SOCKET;
159 }
160
161 /* Check the current open type and use overlapped if it's default */
162 if (!Thread->OpenType) Flags = WSA_FLAG_OVERLAPPED;
163
164 /* Make the protocol negative if this is NETBIOS */
165 if ((af == AF_NETBIOS) && (protocol > 0)) protocol *= -1;
166
167 /* Now let WSA handle it */
168 return WSASocketW(af, type, protocol, NULL, 0, Flags);
169 }
170
171 /*
172 * @unimplemented
173 */
174 INT
175 WSPAPI
WPUCloseSocketHandle(IN SOCKET s,OUT LPINT lpErrno)176 WPUCloseSocketHandle(IN SOCKET s,
177 OUT LPINT lpErrno)
178 {
179 UNIMPLEMENTED;
180 return 0;
181 }
182
183 /*
184 * @unimplemented
185 */
186 SOCKET
187 WSPAPI
WPUCreateSocketHandle(IN DWORD dwCatalogEntryId,IN DWORD_PTR dwContext,OUT LPINT lpErrno)188 WPUCreateSocketHandle(IN DWORD dwCatalogEntryId,
189 IN DWORD_PTR dwContext,
190 OUT LPINT lpErrno)
191 {
192 UNIMPLEMENTED;
193 return (SOCKET)0;
194 }
195
196 /*
197 * @implemented
198 */
199 SOCKET
200 WSPAPI
WPUModifyIFSHandle(IN DWORD dwCatalogEntryId,IN SOCKET ProposedHandle,OUT LPINT lpErrno)201 WPUModifyIFSHandle(IN DWORD dwCatalogEntryId,
202 IN SOCKET ProposedHandle,
203 OUT LPINT lpErrno)
204 {
205 SOCKET Handle = INVALID_SOCKET;
206 DWORD ErrorCode = ERROR_SUCCESS;
207 PWSPROCESS Process;
208 PTCATALOG Catalog;
209 PTCATALOG_ENTRY Entry;
210 PWSSOCKET Socket;
211 DPRINT("WPUModifyIFSHandle: %lx, %lx\n", dwCatalogEntryId, ProposedHandle);
212
213 /* Get the current process */
214 if ((Process = WsGetProcess()))
215 {
216 /* Get the Transport Catalog */
217 if ((Catalog = WsProcGetTCatalog(Process)))
218 {
219 /* Get the entry for this ID */
220 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
221 dwCatalogEntryId,
222 &Entry);
223 /* Check for success */
224 if (ErrorCode == ERROR_SUCCESS)
225 {
226 /* Create a socket object */
227 if ((Socket = WsSockAllocate()))
228 {
229 /* Initialize it */
230 WsSockInitialize(Socket, Entry);
231
232 /* Associate it */
233 ErrorCode = WsSockAssociateHandle(Socket,
234 ProposedHandle,
235 TRUE);
236 /* Check for success */
237 if (ErrorCode == ERROR_SUCCESS)
238 {
239 /* Return */
240 Handle = ProposedHandle;
241 *lpErrno = ERROR_SUCCESS;
242 }
243 else
244 {
245 /* Fail */
246 WsSockDereference(Socket);
247 *lpErrno = ErrorCode;
248 }
249
250 /* Dereference the extra count */
251 WsSockDereference(Socket);
252 }
253 else
254 {
255 /* No memory to allocate a socket */
256 *lpErrno = WSAENOBUFS;
257 }
258
259 /* Dereference the catalog entry */
260 WsTcEntryDereference(Entry);
261 }
262 else
263 {
264 /* Entry not found */
265 *lpErrno = ErrorCode;
266 }
267 }
268 else
269 {
270 /* Catalog not found */
271 *lpErrno = WSANOTINITIALISED;
272 }
273 }
274 else
275 {
276 /* Process not ready */
277 *lpErrno = WSANOTINITIALISED;
278 }
279
280 /* Return */
281 return Handle;
282 }
283
284 /*
285 * @unimplemented
286 */
287 INT
288 WSPAPI
WPUQuerySocketHandleContext(IN SOCKET s,OUT PDWORD_PTR lpContext,OUT LPINT lpErrno)289 WPUQuerySocketHandleContext(IN SOCKET s,
290 OUT PDWORD_PTR lpContext,
291 OUT LPINT lpErrno)
292 {
293 UNIMPLEMENTED;
294 return 0;
295 }
296
297 /*
298 * @implemented
299 */
300 SOCKET
301 WSAAPI
WSAAccept(IN SOCKET s,OUT LPSOCKADDR addr,IN OUT LPINT addrlen,IN LPCONDITIONPROC lpfnCondition,IN DWORD_PTR dwCallbackData)302 WSAAccept(IN SOCKET s,
303 OUT LPSOCKADDR addr,
304 IN OUT LPINT addrlen,
305 IN LPCONDITIONPROC lpfnCondition,
306 IN DWORD_PTR dwCallbackData)
307 {
308 PWSPROCESS Process;
309 PWSTHREAD Thread;
310 PWSSOCKET Socket;
311 DWORD OpenType;
312 INT ErrorCode;
313 SOCKET Status;
314 DPRINT("WSAAccept: %lx, %lx, %lx, %p\n", s, addr, addrlen, lpfnCondition);
315
316 /* Enter prolog */
317 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
318 {
319 /* Get the Socket Context */
320 if ((Socket = WsSockGetSocket(s)))
321 {
322 /* Get the old open type and set new one */
323 OpenType = Thread->OpenType;
324 Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT;
325
326 /* Make the call */
327 Status = Socket->Provider->Service.lpWSPAccept(s,
328 addr,
329 addrlen,
330 lpfnCondition,
331 dwCallbackData,
332 &ErrorCode);
333 /* Restore open type */
334 Thread->OpenType = OpenType;
335
336 /* Deference the Socket Context */
337 WsSockDereference(Socket);
338
339 /* Check if we got a valid socket */
340 if (Status != INVALID_SOCKET)
341 {
342 /* Check if we got a new socket */
343 if (Status != s)
344 {
345 /* Add a new reference */
346 WsSockAddApiReference(Status);
347 }
348
349 /* Return */
350 return Status;
351 }
352 }
353 else
354 {
355 /* No Socket Context Found */
356 ErrorCode = WSAENOTSOCK;
357 }
358 }
359
360 /* Return with an Error */
361 SetLastError(ErrorCode);
362 return INVALID_SOCKET;
363 }
364
365 /*
366 * @implemented
367 */
368 SOCKET
369 WSAAPI
WSAJoinLeaf(IN SOCKET s,IN CONST struct sockaddr * name,IN INT namelen,IN LPWSABUF lpCallerData,OUT LPWSABUF lpCalleeData,IN LPQOS lpSQOS,IN LPQOS lpGQOS,IN DWORD dwFlags)370 WSAJoinLeaf(IN SOCKET s,
371 IN CONST struct sockaddr *name,
372 IN INT namelen,
373 IN LPWSABUF lpCallerData,
374 OUT LPWSABUF lpCalleeData,
375 IN LPQOS lpSQOS,
376 IN LPQOS lpGQOS,
377 IN DWORD dwFlags)
378 {
379 PWSPROCESS Process;
380 PWSTHREAD Thread;
381 PWSSOCKET Socket;
382 DWORD OpenType;
383 INT ErrorCode;
384 SOCKET Status;
385 DPRINT("WSAJoinLeaf: %lx, %lx, %lx\n", s, name, namelen);
386
387 /* Enter prolog */
388 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
389 {
390 /* Get the Socket Context */
391 if ((Socket = WsSockGetSocket(s)))
392 {
393 /* Get the old open type and set new one */
394 OpenType = Thread->OpenType;
395 Thread->OpenType = Socket->Overlapped ? 0 : SO_SYNCHRONOUS_NONALERT;
396
397 /* Make the call */
398 Status = Socket->Provider->Service.lpWSPJoinLeaf(s,
399 name,
400 namelen,
401 lpCallerData,
402 lpCalleeData,
403 lpSQOS,
404 lpGQOS,
405 dwFlags,
406 &ErrorCode);
407 /* Restore open type */
408 Thread->OpenType = OpenType;
409
410 /* Deference the Socket Context */
411 WsSockDereference(Socket);
412
413 /* Check if we got a valid socket */
414 if (Status != INVALID_SOCKET)
415 {
416 /* Check if we got a new socket */
417 if (Status != s)
418 {
419 /* Add a new reference */
420 WsSockAddApiReference(Status);
421 }
422
423 /* Return */
424 return Status;
425 }
426 }
427 else
428 {
429 /* No Socket Context Found */
430 ErrorCode = WSAENOTSOCK;
431 }
432 }
433
434 /* Return with an Error */
435 SetLastError(ErrorCode);
436 return INVALID_SOCKET;
437 }
438
439 /*
440 * @implemented
441 */
442 SOCKET
443 WSAAPI
WSASocketA(IN INT af,IN INT type,IN INT protocol,IN LPWSAPROTOCOL_INFOA lpProtocolInfo,IN GROUP g,IN DWORD dwFlags)444 WSASocketA(IN INT af,
445 IN INT type,
446 IN INT protocol,
447 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
448 IN GROUP g,
449 IN DWORD dwFlags)
450 {
451 WSAPROTOCOL_INFOW ProtocolInfoW;
452 LPWSAPROTOCOL_INFOW p = &ProtocolInfoW;
453
454 /* Convert Protocol Info to Wide */
455 if (lpProtocolInfo)
456 {
457 /* Copy the Data */
458 memcpy(&ProtocolInfoW,
459 lpProtocolInfo,
460 sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
461
462 /* Convert the String */
463 MultiByteToWideChar(CP_ACP,
464 0,
465 lpProtocolInfo->szProtocol,
466 -1,
467 ProtocolInfoW.szProtocol,
468 sizeof(ProtocolInfoW.szProtocol) / sizeof(WCHAR));
469 }
470 else
471 {
472 /* No Protocol Info Specified */
473 p = NULL;
474 }
475
476 /* Call the Unicode Function */
477 return WSASocketW(af,
478 type,
479 protocol,
480 p,
481 g,
482 dwFlags);
483 }
484
485 /*
486 * @implemented
487 */
488 SOCKET
489 WSAAPI
WSASocketW(IN INT af,IN INT type,IN INT protocol,IN LPWSAPROTOCOL_INFOW lpProtocolInfo,IN GROUP g,IN DWORD dwFlags)490 WSASocketW(IN INT af,
491 IN INT type,
492 IN INT protocol,
493 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
494 IN GROUP g,
495 IN DWORD dwFlags)
496 {
497 PWSPROCESS Process;
498 PWSTHREAD Thread;
499 INT ErrorCode;
500 PTCATALOG Catalog;
501 DWORD CatalogId;
502 PTCATALOG_ENTRY CatalogEntry;
503 LPWSAPROTOCOL_INFOW ProtocolInfo;
504 DWORD OpenType;
505 SOCKET Status = INVALID_SOCKET;
506 DPRINT("WSASocketW: %lx, %lx, %lx, %p\n", af, type, protocol, lpProtocolInfo);
507
508 /* Enter prolog */
509 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
510 {
511 /* Fail now */
512 SetLastError(ErrorCode);
513 return INVALID_SOCKET;
514 }
515
516 /* Get the catalog */
517 Catalog = WsProcGetTCatalog(Process);
518
519 /* Find a Provider for the Catalog ID */
520 if (lpProtocolInfo)
521 {
522 /* Get the catalog ID */
523 CatalogId = lpProtocolInfo->dwCatalogEntryId;
524
525 /* Get the Catalog Entry */
526 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog,
527 CatalogId,
528 &CatalogEntry);
529 }
530 else
531 {
532 /* No ID */
533 CatalogId = 0;
534
535 DoLookup:
536 /* Get the Catalog Data from the Socket Info */
537 ErrorCode = WsTcGetEntryFromTriplet(Catalog,
538 af,
539 type,
540 protocol,
541 CatalogId,
542 &CatalogEntry);
543 }
544
545 /* Check for Success */
546 if (ErrorCode == ERROR_SUCCESS)
547 {
548 /* Use the default Protocol Info if none given */
549 ProtocolInfo = lpProtocolInfo ? lpProtocolInfo : &CatalogEntry->ProtocolInfo;
550
551 /* Save the open type and set new one */
552 OpenType = Thread->OpenType;
553 Thread->OpenType = (dwFlags & WSA_FLAG_OVERLAPPED) ?
554 0 : SO_SYNCHRONOUS_NONALERT;
555
556 /* Call the Provider to create the Socket */
557 Status = CatalogEntry->Provider->Service.lpWSPSocket(af,
558 type,
559 protocol,
560 ProtocolInfo,
561 g,
562 dwFlags,
563 &ErrorCode);
564 /* Restore open type */
565 Thread->OpenType = OpenType;
566
567 /* Get the catalog ID now, and dereference */
568 CatalogId = ProtocolInfo->dwCatalogEntryId;
569 WsTcEntryDereference(CatalogEntry);
570
571 /* Did we fail with WSAEINPROGRESS and had no specific provider? */
572 if ((Status == INVALID_SOCKET) &&
573 (ErrorCode == WSAEINPROGRESS) &&
574 !(lpProtocolInfo))
575 {
576 /* In that case, restart the lookup from this ID */
577 goto DoLookup;
578 }
579
580 /* Check if we got a valid socket */
581 if (Status != INVALID_SOCKET)
582 {
583 /* Add an API reference and return */
584 WsSockAddApiReference(Status);
585 return Status;
586 }
587 }
588
589 /* Return with an Error */
590 SetLastError(ErrorCode);
591 return INVALID_SOCKET;
592 }
593