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