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