Create a branch for network fixes.
[reactos.git] / dll / win32 / ws2_32 / misc / dllmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: misc/dllmain.c
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10
11 #include <roscfg.h>
12 #include <w32api.h>
13 #include <ws2_32.h>
14 #include <catalog.h>
15 #include <handle.h>
16 #include <upcall.h>
17
18 #ifdef DBG
19
20 /* See debug.h for debug/trace constants */
21 //DWORD DebugTraceLevel = MIN_TRACE;
22 //DWORD DebugTraceLevel = MAX_TRACE;
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel = 0;
25 #endif /* DBG */
26
27 /* To make the linker happy */
28 VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
29
30 HINSTANCE g_hInstDll;
31 HANDLE GlobalHeap;
32 BOOL WsaInitialized = FALSE; /* TRUE if WSAStartup() has been successfully called */
33 WSPUPCALLTABLE UpcallTable;
34
35
36 /*
37 * @implemented
38 */
39 INT
40 EXPORT
41 WSAGetLastError(VOID)
42 {
43 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
44
45 if (p)
46 {
47 return p->LastErrorValue;
48 }
49 else
50 {
51 /* FIXME: What error code should we use here? Can this even happen? */
52 return ERROR_BAD_ENVIRONMENT;
53 }
54 }
55
56
57 /*
58 * @implemented
59 */
60 VOID
61 EXPORT
62 WSASetLastError(IN INT iError)
63 {
64 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
65
66 if (p)
67 p->LastErrorValue = iError;
68 }
69
70
71 /*
72 * @implemented
73 */
74 INT
75 EXPORT
76 WSAStartup(IN WORD wVersionRequested,
77 OUT LPWSADATA lpWSAData)
78 {
79 BYTE Low, High;
80
81 WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
82
83 if (!g_hInstDll)
84 return WSASYSNOTREADY;
85
86 if (lpWSAData == NULL)
87 return WSAEFAULT;
88
89 Low = LOBYTE(wVersionRequested);
90 High = HIBYTE(wVersionRequested);
91
92 if (Low < 1)
93 {
94 WS_DbgPrint(MAX_TRACE, ("Bad winsock version requested, %d,%d", Low, High));
95 return WSAVERNOTSUPPORTED;
96 }
97
98 if (Low == 1)
99 {
100 if (High == 0)
101 {
102 lpWSAData->wVersion = wVersionRequested;
103 }
104 else
105 {
106 lpWSAData->wVersion = MAKEWORD(1, 1);
107 }
108 }
109 else if (Low == 2)
110 {
111 if (High <= 2)
112 {
113 lpWSAData->wVersion = MAKEWORD(2, High);
114 }
115 else
116 {
117 lpWSAData->wVersion = MAKEWORD(2, 2);
118 }
119 }
120 else
121 {
122 lpWSAData->wVersion = MAKEWORD(2, 2);
123 }
124
125 lpWSAData->wVersion = wVersionRequested;
126 lpWSAData->wHighVersion = MAKEWORD(2,2);
127 lstrcpyA(lpWSAData->szDescription, "WinSock 2.2");
128 lstrcpyA(lpWSAData->szSystemStatus, "Running");
129 lpWSAData->iMaxSockets = 0;
130 lpWSAData->iMaxUdpDg = 0;
131 lpWSAData->lpVendorInfo = NULL;
132
133 /*FIXME: increment internal counter */
134
135 WSASETINITIALIZED;
136
137 return NO_ERROR;
138 }
139
140
141 /*
142 * @implemented
143 */
144 INT
145 EXPORT
146 WSACleanup(VOID)
147 {
148 WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
149
150 if (!WSAINITIALIZED)
151 {
152 WSASetLastError(WSANOTINITIALISED);
153 return WSANOTINITIALISED;
154 }
155
156 return NO_ERROR;
157 }
158
159
160 /*
161 * @implemented
162 */
163 SOCKET
164 EXPORT
165 socket(IN INT af,
166 IN INT type,
167 IN INT protocol)
168 {
169 return WSASocketW(af,
170 type,
171 protocol,
172 NULL,
173 0,
174 0);
175 }
176
177
178 /*
179 * @implemented
180 */
181 SOCKET
182 EXPORT
183 WSASocketA(IN INT af,
184 IN INT type,
185 IN INT protocol,
186 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
187 IN GROUP g,
188 IN DWORD dwFlags)
189 /*
190 * FUNCTION: Creates a new socket
191 */
192 {
193 WSAPROTOCOL_INFOW ProtocolInfoW;
194 LPWSAPROTOCOL_INFOW p;
195 UNICODE_STRING StringU;
196 ANSI_STRING StringA;
197
198 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
199 af, type, protocol));
200
201 if (lpProtocolInfo)
202 {
203 memcpy(&ProtocolInfoW,
204 lpProtocolInfo,
205 sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
206 RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
207 RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
208 RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
209 p = &ProtocolInfoW;
210 }
211 else
212 {
213 p = NULL;
214 }
215
216 return WSASocketW(af,
217 type,
218 protocol,
219 p,
220 g,
221 dwFlags);
222 }
223
224
225 /*
226 * @implemented
227 */
228 SOCKET
229 EXPORT
230 WSASocketW(IN INT af,
231 IN INT type,
232 IN INT protocol,
233 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
234 IN GROUP g,
235 IN DWORD dwFlags)
236 /*
237 * FUNCTION: Creates a new socket descriptor
238 * ARGUMENTS:
239 * af = Address family
240 * type = Socket type
241 * protocol = Protocol type
242 * lpProtocolInfo = Pointer to protocol information
243 * g = Reserved
244 * dwFlags = Socket flags
245 * RETURNS:
246 * Created socket descriptor, or INVALID_SOCKET if it could not be created
247 */
248 {
249 INT Status;
250 SOCKET Socket;
251 PCATALOG_ENTRY Provider;
252 WSAPROTOCOL_INFOW ProtocolInfo;
253
254 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
255 af, type, protocol));
256
257 if (!WSAINITIALIZED)
258 {
259 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
260 af, type, protocol));
261 WSASetLastError(WSANOTINITIALISED);
262 return INVALID_SOCKET;
263 }
264
265 if (!lpProtocolInfo)
266 {
267 lpProtocolInfo = &ProtocolInfo;
268 ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
269
270 ProtocolInfo.iAddressFamily = af;
271 ProtocolInfo.iSocketType = type;
272 ProtocolInfo.iProtocol = protocol;
273 }
274
275 Provider = LocateProvider(lpProtocolInfo);
276 if (!Provider)
277 {
278 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
279 af, type, protocol));
280 WSASetLastError(WSAEAFNOSUPPORT);
281 return INVALID_SOCKET;
282 }
283
284 Status = LoadProvider(Provider, lpProtocolInfo);
285 if (Status != NO_ERROR)
286 {
287 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = %d.\n",
288 af, type, protocol, Status));
289 WSASetLastError(Status);
290 return INVALID_SOCKET;
291 }
292
293 WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
294 Provider->ProcTable.lpWSPSocket));
295
296 assert(Provider->ProcTable.lpWSPSocket);
297
298 WS_DbgPrint(MAX_TRACE,("About to call provider socket fn\n"));
299
300 Socket = Provider->ProcTable.lpWSPSocket(af,
301 type,
302 protocol,
303 lpProtocolInfo,
304 g,
305 dwFlags,
306 &Status);
307
308 WS_DbgPrint(MAX_TRACE,("Socket: %x, Status: %x\n", Socket, Status));
309
310 if (Status != NO_ERROR)
311 {
312 WSASetLastError(Status);
313 return INVALID_SOCKET;
314 }
315
316 WS_DbgPrint(MAX_TRACE,("Status: %x\n", Status));
317
318 return Socket;
319 }
320
321
322 /*
323 * @implemented
324 */
325 INT
326 EXPORT
327 closesocket(IN SOCKET s)
328 /*
329 * FUNCTION: Closes a socket descriptor
330 * ARGUMENTS:
331 * s = Socket descriptor
332 * RETURNS:
333 * 0, or SOCKET_ERROR if an error ocurred
334 */
335 {
336 PCATALOG_ENTRY Provider;
337 INT Status;
338 INT Errno;
339
340 WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
341
342 if (!WSAINITIALIZED)
343 {
344 WSASetLastError(WSANOTINITIALISED);
345 return SOCKET_ERROR;
346 }
347
348 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
349 {
350 WSASetLastError(WSAENOTSOCK);
351 return SOCKET_ERROR;
352 }
353
354 CloseProviderHandle((HANDLE)s);
355
356 WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle\n"));
357
358 DereferenceProviderByPointer(Provider);
359
360 WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle Done\n"));
361
362 Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
363
364 WS_DbgPrint(MAX_TRACE,("Provider Close Done\n"));
365
366 if (Status == SOCKET_ERROR)
367 WSASetLastError(Errno);
368
369 WS_DbgPrint(MAX_TRACE,("Returning success\n"));
370
371 return 0;
372 }
373
374
375 /*
376 * @implemented
377 */
378 INT
379 EXPORT
380 select(IN INT nfds,
381 IN OUT LPFD_SET readfds,
382 IN OUT LPFD_SET writefds,
383 IN OUT LPFD_SET exceptfds,
384 IN CONST struct timeval *timeout)
385 /*
386 * FUNCTION: Returns status of one or more sockets
387 * ARGUMENTS:
388 * nfds = Always ignored
389 * readfds = Pointer to socket set to be checked for readability (optional)
390 * writefds = Pointer to socket set to be checked for writability (optional)
391 * exceptfds = Pointer to socket set to be checked for errors (optional)
392 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
393 * (NULL means wait forever)
394 * RETURNS:
395 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
396 */
397 {
398 PCATALOG_ENTRY Provider = NULL;
399 INT Count;
400 INT Errno;
401
402 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
403 readfds, writefds, exceptfds));
404
405 if (!WSAINITIALIZED)
406 {
407 WSASetLastError(WSANOTINITIALISED);
408 WS_DbgPrint(MID_TRACE,("Not initialized\n"));
409 return SOCKET_ERROR;
410 }
411
412 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
413
414 /* FIXME: For now, assume only one service provider */
415 if ((readfds != NULL) && (readfds->fd_count > 0))
416 {
417 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0],
418 &Provider))
419 {
420 WSASetLastError(WSAENOTSOCK);
421 WS_DbgPrint(MID_TRACE,("No provider (read)\n"));
422 return SOCKET_ERROR;
423 }
424 }
425 else if ((writefds != NULL) && (writefds->fd_count > 0))
426 {
427 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0],
428 &Provider))
429 {
430 WSASetLastError(WSAENOTSOCK);
431 WS_DbgPrint(MID_TRACE,("No provider (write)\n"));
432 return SOCKET_ERROR;
433 }
434 }
435 else if ((exceptfds != NULL) && (exceptfds->fd_count > 0))
436 {
437 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider))
438 {
439 WSASetLastError(WSAENOTSOCK);
440 WS_DbgPrint(MID_TRACE,("No provider (err)\n"));
441 return SOCKET_ERROR;
442 }
443 #if 0 /* XXX empty select is not an error */
444 }
445 else
446 {
447 WSASetLastError(WSAEINVAL);
448 return SOCKET_ERROR;
449 #endif
450 }
451
452 if ( !Provider )
453 {
454 if ( timeout )
455 {
456 WS_DbgPrint(MID_TRACE,("Select: used as timer\n"));
457 Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) );
458 }
459 return 0;
460 }
461 else if (Provider->ProcTable.lpWSPSelect)
462 {
463 WS_DbgPrint(MID_TRACE,("Calling WSPSelect:%x\n", Provider->ProcTable.lpWSPSelect));
464 Count = Provider->ProcTable.lpWSPSelect(nfds,
465 readfds,
466 writefds,
467 exceptfds,
468 (LPTIMEVAL)timeout,
469 &Errno);
470
471 WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n",
472 Provider, Count, Errno));
473
474 DereferenceProviderByPointer(Provider);
475
476 if (Errno != NO_ERROR)
477 {
478 WSASetLastError(Errno);
479 return SOCKET_ERROR;
480 }
481 }
482 else
483 {
484 WSASetLastError(WSAEINVAL);
485 return SOCKET_ERROR;
486 }
487
488 return Count;
489 }
490
491
492 /*
493 * @implemented
494 */
495 INT
496 EXPORT
497 bind(IN SOCKET s,
498 IN CONST struct sockaddr *name,
499 IN INT namelen)
500 {
501 PCATALOG_ENTRY Provider;
502 INT Status;
503 INT Errno;
504
505 if (!WSAINITIALIZED)
506 {
507 WSASetLastError(WSANOTINITIALISED);
508 return SOCKET_ERROR;
509 }
510
511 if (!ReferenceProviderByHandle((HANDLE)s,
512 &Provider))
513 {
514 WSASetLastError(WSAENOTSOCK);
515 return SOCKET_ERROR;
516 }
517
518 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
519 Status = Provider->ProcTable.lpWSPBind(s,
520 (CONST LPSOCKADDR)name,
521 namelen,
522 &Errno);
523 #else
524 Status = Provider->ProcTable.lpWSPBind(s,
525 name,
526 namelen,
527 &Errno);
528 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
529
530 DereferenceProviderByPointer(Provider);
531
532 if (Status == SOCKET_ERROR)
533 WSASetLastError(Errno);
534
535 return Status;
536 }
537
538
539 /*
540 * @implemented
541 */
542 INT
543 EXPORT
544 listen(IN SOCKET s,
545 IN INT backlog)
546 {
547 PCATALOG_ENTRY Provider;
548 INT Status;
549 INT Errno;
550
551 if (!WSAINITIALIZED)
552 {
553 WSASetLastError(WSANOTINITIALISED);
554 return SOCKET_ERROR;
555 }
556
557 if (!ReferenceProviderByHandle((HANDLE)s,
558 &Provider))
559 {
560 WSASetLastError(WSAENOTSOCK);
561 return SOCKET_ERROR;
562 }
563
564 Status = Provider->ProcTable.lpWSPListen(s,
565 backlog,
566 &Errno);
567
568 DereferenceProviderByPointer(Provider);
569
570 if (Status == SOCKET_ERROR)
571 WSASetLastError(Errno);
572
573 return Status;
574 }
575
576
577 /*
578 * @implemented
579 */
580 SOCKET
581 EXPORT
582 accept(IN SOCKET s,
583 OUT LPSOCKADDR addr,
584 OUT INT FAR* addrlen)
585 {
586 return WSAAccept(s,
587 addr,
588 addrlen,
589 NULL,
590 0);
591 }
592
593
594 /*
595 * @implemented
596 */
597 INT
598 EXPORT
599 ioctlsocket(IN SOCKET s,
600 IN LONG cmd,
601 IN OUT ULONG FAR* argp)
602 {
603 return WSAIoctl(s,
604 cmd,
605 argp,
606 sizeof(ULONG),
607 argp,
608 sizeof(ULONG),
609 argp,
610 0,
611 0);
612 }
613
614
615 /*
616 * @implemented
617 */
618 SOCKET
619 EXPORT
620 WSAAccept(IN SOCKET s,
621 OUT LPSOCKADDR addr,
622 IN OUT LPINT addrlen,
623 IN LPCONDITIONPROC lpfnCondition,
624 IN DWORD dwCallbackData)
625 {
626 PCATALOG_ENTRY Provider;
627 SOCKET Socket;
628 INT Errno;
629
630 if (!WSAINITIALIZED)
631 {
632 WSASetLastError(WSANOTINITIALISED);
633 return SOCKET_ERROR;
634 }
635
636 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
637 {
638 WSASetLastError(WSAENOTSOCK);
639 return SOCKET_ERROR;
640 }
641
642 WS_DbgPrint(MAX_TRACE,("Calling provider accept\n"));
643
644 Socket = Provider->ProcTable.lpWSPAccept(s,
645 addr,
646 addrlen,
647 lpfnCondition,
648 dwCallbackData,
649 &Errno);
650
651 WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n",
652 Socket, Errno));
653
654 DereferenceProviderByPointer(Provider);
655
656 if (Socket == INVALID_SOCKET)
657 WSASetLastError(Errno);
658
659 if ( addr )
660 {
661 #ifdef DBG
662 LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr;
663 WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n",
664 sa->sin_family,
665 inet_ntoa(sa->sin_addr),
666 ntohs(sa->sin_port),
667 *addrlen));
668 #endif
669 }
670
671 return Socket;
672 }
673
674
675 /*
676 * @implemented
677 */
678 INT
679 EXPORT
680 connect(IN SOCKET s,
681 IN CONST struct sockaddr *name,
682 IN INT namelen)
683 {
684 return WSAConnect(s,
685 name,
686 namelen,
687 NULL,
688 NULL,
689 NULL,
690 NULL);
691 }
692
693
694 /*
695 * @implemented
696 */
697 INT
698 EXPORT
699 WSAConnect(IN SOCKET s,
700 IN CONST struct sockaddr *name,
701 IN INT namelen,
702 IN LPWSABUF lpCallerData,
703 OUT LPWSABUF lpCalleeData,
704 IN LPQOS lpSQOS,
705 IN LPQOS lpGQOS)
706 {
707 PCATALOG_ENTRY Provider;
708 INT Status;
709 INT Errno;
710
711 if (!WSAINITIALIZED)
712 {
713 WSASetLastError(WSANOTINITIALISED);
714 return SOCKET_ERROR;
715 }
716
717 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
718 {
719 WSASetLastError(WSAENOTSOCK);
720 return SOCKET_ERROR;
721 }
722
723 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
724 Status = Provider->ProcTable.lpWSPConnect(s,
725 (CONST LPSOCKADDR)name,
726 namelen,
727 lpCallerData,
728 lpCalleeData,
729 lpSQOS,
730 lpGQOS,
731 &Errno);
732 #else
733 Status = Provider->ProcTable.lpWSPConnect(s,
734 name,
735 namelen,
736 lpCallerData,
737 lpCalleeData,
738 lpSQOS,
739 lpGQOS,
740 &Errno);
741 #endif
742
743 DereferenceProviderByPointer(Provider);
744
745 if (Status == SOCKET_ERROR)
746 WSASetLastError(Errno);
747
748 return Status;
749 }
750
751
752 /*
753 * @implemented
754 */
755 INT
756 EXPORT
757 WSAIoctl(IN SOCKET s,
758 IN DWORD dwIoControlCode,
759 IN LPVOID lpvInBuffer,
760 IN DWORD cbInBuffer,
761 OUT LPVOID lpvOutBuffer,
762 IN DWORD cbOutBuffer,
763 OUT LPDWORD lpcbBytesReturned,
764 IN LPWSAOVERLAPPED lpOverlapped,
765 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
766 {
767 PCATALOG_ENTRY Provider;
768 INT Status;
769 INT Errno;
770
771 if (!WSAINITIALIZED)
772 {
773 WSASetLastError(WSANOTINITIALISED);
774 return SOCKET_ERROR;
775 }
776
777 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
778 {
779 WSASetLastError(WSAENOTSOCK);
780 return SOCKET_ERROR;
781 }
782
783 Status = Provider->ProcTable.lpWSPIoctl(s,
784 dwIoControlCode,
785 lpvInBuffer,
786 cbInBuffer,
787 lpvOutBuffer,
788 cbOutBuffer,
789 lpcbBytesReturned,
790 lpOverlapped,
791 lpCompletionRoutine,
792 NULL /* lpThreadId */,
793 &Errno);
794
795 DereferenceProviderByPointer(Provider);
796
797 if (Status == SOCKET_ERROR)
798 WSASetLastError(Errno);
799
800 return Status;
801 }
802
803 /*
804 * @implemented
805 */
806 INT
807 EXPORT
808 __WSAFDIsSet(SOCKET s, LPFD_SET set)
809 {
810 unsigned int i;
811
812 for ( i = 0; i < set->fd_count; i++ )
813 if ( set->fd_array[i] == s ) return TRUE;
814
815 return FALSE;
816 }
817
818 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p)
819 {
820 if (p)
821 {
822 if (p->Hostent) { free_hostent(p->Hostent); p->Hostent = 0; }
823 if (p->Getservbyname){}
824 if (p->Getservbyport) {}
825 }
826 }
827
828 BOOL
829 STDCALL
830 DllMain(HANDLE hInstDll,
831 ULONG dwReason,
832 LPVOID lpReserved)
833 {
834 PWINSOCK_THREAD_BLOCK p;
835
836 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
837
838 switch (dwReason)
839 {
840 case DLL_PROCESS_ATTACH:
841 {
842 GlobalHeap = GetProcessHeap();
843
844 g_hInstDll = hInstDll;
845
846 CreateCatalog();
847
848 InitProviderHandleTable();
849
850 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
851 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
852 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
853 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
854 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
855 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
856 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
857 UpcallTable.lpWPUPostMessage = PostMessageW;
858 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
859 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
860 UpcallTable.lpWPUQueueApc = WPUQueueApc;
861 UpcallTable.lpWPUResetEvent = WPUResetEvent;
862 UpcallTable.lpWPUSetEvent = WPUSetEvent;
863 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
864 UpcallTable.lpWPUCloseThread = WPUCloseThread;
865
866 /* Fall through to thread attachment handler */
867 }
868 case DLL_THREAD_ATTACH:
869 {
870 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
871
872 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
873
874 if (!p) {
875 return FALSE;
876 }
877
878 p->Hostent = NULL;
879 p->LastErrorValue = NO_ERROR;
880 p->Getservbyname = NULL;
881 p->Getservbyport = NULL;
882
883 NtCurrentTeb()->WinSockData = p;
884 }
885 break;
886
887 case DLL_PROCESS_DETACH:
888 {
889 p = NtCurrentTeb()->WinSockData;
890
891 if (p)
892 HeapFree(GlobalHeap, 0, p);
893
894 DestroyCatalog();
895
896 FreeProviderHandleTable();
897 }
898 break;
899
900 case DLL_THREAD_DETACH:
901 {
902 p = NtCurrentTeb()->WinSockData;
903
904 if (p)
905 HeapFree(GlobalHeap, 0, p);
906 }
907 break;
908 }
909
910 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
911
912 return TRUE;
913 }
914
915 /* EOF */