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