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