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